You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jena.apache.org by "A. Soroka" <aj...@virginia.edu> on 2016/04/11 21:30:48 UTC

TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

A separation was recently introduced by Andy between Transactional (application-side interface) and TransactionalComponent (system-side interface) interfaces, which I believe I understand and definitely support. Additionally, a TransactionalNotSupportedMixin interface was introduced in order to support "un-Transactional" behavior. It extends Transactional and provides default implementations for the methods in Transactional that throw UnsupportedOperationExceptions.

My question: should TransactionalNotSupportedMixin actually be the "override" for Transactional (as it currently is), or for TransactionalComponent, or oddly, for both? Would it be more appropriate to introduce a new NonTransactionalComponent mixin or the like? I suspect that it would be, because we want Transactional and TransactionalComponent to be able to evolve with some real independence, but I also suspect that I am missing something here. {grin}

(For context, this came up for me looking at JENA-1084 as I try to tease apart different kinds of behavior in the TxnInMem dataset impl and amongst them, transactionality. That impl uses a design wherein tuple tables, each for a particular order of columns, are coupled up into multiplex tables that can support all queries. So the question of how to correctly combine transactional and non-transactional code is practical. I started using TransactionalNotSupportedMixin to mark non-transactional implementation code, but now I'm confident that I was wrong and that the "override" for TransactionalComponent is what I really want, but it's not there! {grin})



---
A. Soroka
The University of Virginia Library


Re: TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

Posted by "A. Soroka" <aj...@virginia.edu>.
> Let's close 1084.  That's about i TIM good enough - it is.
> 
> Experimentation on better TIM is good and might result in some more JIRA; first step is the experimentation and maybe looking at what other datastructures are candidates.
> 
> If it's "copy on first write, then update in place (= same W transaction, same thread)" no locking is needed.  Which is good.

Cool. That's definitely the direction I am trying ("mutate-in-place" strictly within a snapshot-isolated transaction, which for Jena, for now, means inside the thread). I am looking hard for the datastructure to support this well. The current contender is the CTrie of Prokopec, Bronson, Bagwell and Odersky [1,2], with O(log n) costs for the mutations and O(1) cost for a snapshot. As Jena gets past the "one transaction per thread at a time, no sharing transactions between threads" mode, I think the costs of concurrency will be worthwhile. But maybe I am being too "blue-sky" there... In any event, I am trying to understand if it is possible to introduce low-cost mutate-in-place operations if we can make the assumptions about concurrency that we know we can make for our case.

[1] http://infoscience.epfl.ch/record/166908/files/ctries-techreport.pdf
[2] http://lamp.epfl.ch/~prokopec/ctries-snapshot.pdf [Here they introduce the snapshot operation]
---
A. Soroka
The University of Virginia Library



Re: TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

Posted by "A. Soroka" <aj...@virginia.edu>.
I've seen that happen (per language spec) when two implemented methods with the same signature are available via different paths of inheritance. That didn't used to be possible, but now it is via default methods. In fact, I saw that very thing in this case because I had a class that inherited impled methods from TransactionalComponent and also impled TransactionalNotSupportedMixin. I had to explicitly choose one or the other. Maybe that was what you saw?

I agree that TransactionalNotSupportedMixin isn't working very well right now. I think we should either remove it or document it to within an inch of its life. Even then, it doesn't save that much typing…

---
A. Soroka
The University of Virginia Library

> On Apr 16, 2016, at 6:25 AM, Andy Seaborne <an...@apache.org> wrote:
> 
> PS
> 
> See the comments in TransactionalNotSupported
> 
> The Eclipse compiler flagged up errors when multiple routes to the same implementation of a interface method happened.  Whether it is right or wrong by the language spec I don't know.
> 
> Hence the TransactionalNotSupportedMixin should be considered a failed experiment.
> 
> Shall we remove it? It's only used in one place and that's in test code.
> 
> 	Andy
> 
> On 16/04/16 11:18, Andy Seaborne wrote:
>> On 14/04/16 21:17, A. Soroka wrote:
>>> On Apr 12, 2016, at 8:24 AM, Andy Seaborne <an...@apache.org> wrote:
>>>> A "Transactional" is the client facing API for the whole set of
>>>> components going to make the sub-system. "TransactionalComponent"
>>>> is what makes up "Transactional"s.  For TIM, they look quite
>>>> similar because there is no worrying about stuff on disk or
>>>> recovery.
>>> 
>>> Okay, good, my starting understanding was basically right.
>>> 
>>> <Mantis example snipped>
>>> 
>>>> I'm not sure what a component that does not offer transaction
>>>> support would mean - either it's transaction oblivious, so does not
>>>> need the interface, or its controlled by a component, in which case
>>>> the TransactionalComponent-ness is elsewhere.
>>>> Transaction/non-transactions is a feature fo the combined set of
>>>> components. If one does not play the game and is needed, the match
>>>> is off.
>>> 
>>> I didn't do a good job of expressing my problem. It's not the case
>>> that you describe, where a component simply doesn't support
>>> transactions. It's the case where a contracting type would be
>>> expected to support transactions but doesn't because of impl
>>> limitations. For example, a DatasetGraph extends Transactional, but
>>> some DatasetGraphs really can't support transactions. My
>>> understanding was that that's the point where you bring in
>>> TransactionalNotSupportedMixin, to indicate that fact, and I was
>>> looking for the equivalent for TransactionalComponent. But maybe I am
>>> misunderstanding TransactionalNotSupportedMixin?
>> 
>> What component are you thinking of?
>> 
>> DatasetGraph indicate it with "supportsTransactions() -> false"
>> and supportsTransactionAbort() for the "true, but no abort case" that
>> than a interface indicator.
>> 
>> TransactionalNotSupportedMixin is just a convenient shorhand for writing
>> out the cases of "unsupported".
>> 
>> And the style does not work every where - e.g. DatasetGraphMapLink where
>> multiple inheritance is needed as the Transactional part has state but
>> the class is already a subclass.  (is there a better way round that? The
>> code uses pure "implementation inheritance" - i.e. a bunch of call
>> throughs on a private member.)
>> 
>> 
>> Mixin, to me, is an implementation style to add some functions to a
>> class without being a stateful super class.  Kinda didn't work very
>> well, TransactionalNotSupportedMixin is only used once.
>> 
>> Though I read that using default methods in an interface like that is
>> bad style - I don't know why though.
>> 
>>>> I was looking at space used for the new parser caching but a side
>>>> effect is a few preliminary timing figures. Here are updated
>>>> figures for Jena latest with dexx 0.6, one run to warm up the JIT
>>>> first.
>>> <figures snipped>
>>>> dexx 0.6 didn't make a noticeable different and it looks like TIM
>>>> is acceptably slower and does not use much more space.
>>>> 
>>>> Now, whether there are optimizations in TIM that can bring down the
>>>> time, is the big question.
>>> 
>>> Well, this may make JENA-1084 pointless, in the best possible way!
>> 
>> :-)
>> 
>> Let's close 1084.  That's about i TIM good enough - it is.
>> 
>> Experimentation on better TIM is good and might result in some more
>> JIRA; first step is the experimentation and maybe looking at what other
>> datastructures are candidates.
>> 
>> If it's "copy on first write, then update in place (= same W
>> transaction, same thread)" no locking is needed.  Which is good.
>> 
>>> Yes, I think there are optimizations available. How much they will
>>> do, I can't say with any certainty. But I can certainly start looking
>>> at them. The one that I would most like to work on would be the use
>>> of "mutate-in-place" extensions for the persistent data structures,
>>> but Dexx isn't contemplating that (it's basically a port of the Scala
>>> data structure library) and I'm not sure how easy it would be to
>>> "graft" that on. There's also the fact that ideally, we would like
>>> "in-place" to mean "in a transaction", but unlike Mantis, we don't
>>> yet have a real object that is the transaction. We're still letting
>>> threads stand in for that.
>>> 
>>> --- A. Soroka The University of Virginia Library
>>> 
>> 
> 


Re: TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

Posted by Andy Seaborne <an...@apache.org>.
PS

See the comments in TransactionalNotSupported

The Eclipse compiler flagged up errors when multiple routes to the same 
implementation of a interface method happened.  Whether it is right or 
wrong by the language spec I don't know.

Hence the TransactionalNotSupportedMixin should be considered a failed 
experiment.

Shall we remove it? It's only used in one place and that's in test code.

	Andy

On 16/04/16 11:18, Andy Seaborne wrote:
> On 14/04/16 21:17, A. Soroka wrote:
>> On Apr 12, 2016, at 8:24 AM, Andy Seaborne <an...@apache.org> wrote:
>>> A "Transactional" is the client facing API for the whole set of
>>> components going to make the sub-system. "TransactionalComponent"
>>> is what makes up "Transactional"s.  For TIM, they look quite
>>> similar because there is no worrying about stuff on disk or
>>> recovery.
>>
>> Okay, good, my starting understanding was basically right.
>>
>> <Mantis example snipped>
>>
>>> I'm not sure what a component that does not offer transaction
>>> support would mean - either it's transaction oblivious, so does not
>>> need the interface, or its controlled by a component, in which case
>>> the TransactionalComponent-ness is elsewhere.
>>> Transaction/non-transactions is a feature fo the combined set of
>>> components. If one does not play the game and is needed, the match
>>> is off.
>>
>> I didn't do a good job of expressing my problem. It's not the case
>> that you describe, where a component simply doesn't support
>> transactions. It's the case where a contracting type would be
>> expected to support transactions but doesn't because of impl
>> limitations. For example, a DatasetGraph extends Transactional, but
>> some DatasetGraphs really can't support transactions. My
>> understanding was that that's the point where you bring in
>> TransactionalNotSupportedMixin, to indicate that fact, and I was
>> looking for the equivalent for TransactionalComponent. But maybe I am
>> misunderstanding TransactionalNotSupportedMixin?
>
> What component are you thinking of?
>
> DatasetGraph indicate it with "supportsTransactions() -> false"
> and supportsTransactionAbort() for the "true, but no abort case" that
> than a interface indicator.
>
> TransactionalNotSupportedMixin is just a convenient shorhand for writing
> out the cases of "unsupported".
>
> And the style does not work every where - e.g. DatasetGraphMapLink where
> multiple inheritance is needed as the Transactional part has state but
> the class is already a subclass.  (is there a better way round that? The
> code uses pure "implementation inheritance" - i.e. a bunch of call
> throughs on a private member.)
>
>
> Mixin, to me, is an implementation style to add some functions to a
> class without being a stateful super class.  Kinda didn't work very
> well, TransactionalNotSupportedMixin is only used once.
>
> Though I read that using default methods in an interface like that is
> bad style - I don't know why though.
>
>>> I was looking at space used for the new parser caching but a side
>>> effect is a few preliminary timing figures. Here are updated
>>> figures for Jena latest with dexx 0.6, one run to warm up the JIT
>>> first.
>> <figures snipped>
>>> dexx 0.6 didn't make a noticeable different and it looks like TIM
>>> is acceptably slower and does not use much more space.
>>>
>>> Now, whether there are optimizations in TIM that can bring down the
>>> time, is the big question.
>>
>> Well, this may make JENA-1084 pointless, in the best possible way!
>
> :-)
>
> Let's close 1084.  That's about i TIM good enough - it is.
>
> Experimentation on better TIM is good and might result in some more
> JIRA; first step is the experimentation and maybe looking at what other
> datastructures are candidates.
>
> If it's "copy on first write, then update in place (= same W
> transaction, same thread)" no locking is needed.  Which is good.
>
>> Yes, I think there are optimizations available. How much they will
>> do, I can't say with any certainty. But I can certainly start looking
>> at them. The one that I would most like to work on would be the use
>> of "mutate-in-place" extensions for the persistent data structures,
>> but Dexx isn't contemplating that (it's basically a port of the Scala
>> data structure library) and I'm not sure how easy it would be to
>> "graft" that on. There's also the fact that ideally, we would like
>> "in-place" to mean "in a transaction", but unlike Mantis, we don't
>> yet have a real object that is the transaction. We're still letting
>> threads stand in for that.
>>
>> --- A. Soroka The University of Virginia Library
>>
>


Re: TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

Posted by Andy Seaborne <an...@apache.org>.
On 14/04/16 21:17, A. Soroka wrote:
> On Apr 12, 2016, at 8:24 AM, Andy Seaborne <an...@apache.org> wrote:
>> A "Transactional" is the client facing API for the whole set of
>> components going to make the sub-system. "TransactionalComponent"
>> is what makes up "Transactional"s.  For TIM, they look quite
>> similar because there is no worrying about stuff on disk or
>> recovery.
>
> Okay, good, my starting understanding was basically right.
>
> <Mantis example snipped>
>
>> I'm not sure what a component that does not offer transaction
>> support would mean - either it's transaction oblivious, so does not
>> need the interface, or its controlled by a component, in which case
>> the TransactionalComponent-ness is elsewhere.
>> Transaction/non-transactions is a feature fo the combined set of
>> components. If one does not play the game and is needed, the match
>> is off.
>
> I didn't do a good job of expressing my problem. It's not the case
> that you describe, where a component simply doesn't support
> transactions. It's the case where a contracting type would be
> expected to support transactions but doesn't because of impl
> limitations. For example, a DatasetGraph extends Transactional, but
> some DatasetGraphs really can't support transactions. My
> understanding was that that's the point where you bring in
> TransactionalNotSupportedMixin, to indicate that fact, and I was
> looking for the equivalent for TransactionalComponent. But maybe I am
> misunderstanding TransactionalNotSupportedMixin?

What component are you thinking of?

DatasetGraph indicate it with "supportsTransactions() -> false"
and supportsTransactionAbort() for the "true, but no abort case" that 
than a interface indicator.

TransactionalNotSupportedMixin is just a convenient shorhand for writing 
out the cases of "unsupported".

And the style does not work every where - e.g. DatasetGraphMapLink where 
multiple inheritance is needed as the Transactional part has state but 
the class is already a subclass.  (is there a better way round that? The 
code uses pure "implementation inheritance" - i.e. a bunch of call 
throughs on a private member.)


Mixin, to me, is an implementation style to add some functions to a 
class without being a stateful super class.  Kinda didn't work very 
well, TransactionalNotSupportedMixin is only used once.

Though I read that using default methods in an interface like that is 
bad style - I don't know why though.

>> I was looking at space used for the new parser caching but a side
>> effect is a few preliminary timing figures. Here are updated
>> figures for Jena latest with dexx 0.6, one run to warm up the JIT
>> first.
> <figures snipped>
>> dexx 0.6 didn't make a noticeable different and it looks like TIM
>> is acceptably slower and does not use much more space.
>>
>> Now, whether there are optimizations in TIM that can bring down the
>> time, is the big question.
>
> Well, this may make JENA-1084 pointless, in the best possible way!

:-)

Let's close 1084.  That's about i TIM good enough - it is.

Experimentation on better TIM is good and might result in some more 
JIRA; first step is the experimentation and maybe looking at what other 
datastructures are candidates.

If it's "copy on first write, then update in place (= same W 
transaction, same thread)" no locking is needed.  Which is good.

> Yes, I think there are optimizations available. How much they will
> do, I can't say with any certainty. But I can certainly start looking
> at them. The one that I would most like to work on would be the use
> of "mutate-in-place" extensions for the persistent data structures,
> but Dexx isn't contemplating that (it's basically a port of the Scala
> data structure library) and I'm not sure how easy it would be to
> "graft" that on. There's also the fact that ideally, we would like
> "in-place" to mean "in a transaction", but unlike Mantis, we don't
> yet have a real object that is the transaction. We're still letting
> threads stand in for that.
>
> --- A. Soroka The University of Virginia Library
>


Re: TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

Posted by "A. Soroka" <aj...@virginia.edu>.
On Apr 12, 2016, at 8:24 AM, Andy Seaborne <an...@apache.org> wrote:
> A "Transactional" is the client facing API for the whole set of components going to make the sub-system.
> "TransactionalComponent" is what makes up "Transactional"s.  For TIM, they look quite similar because there is no worrying about stuff on disk or recovery.

Okay, good, my starting understanding was basically right.

<Mantis example snipped>

> I'm not sure what a component that does not offer transaction support would mean - either it's transaction oblivious, so does not need the interface, or its controlled by a component, in which case the TransactionalComponent-ness is elsewhere.  Transaction/non-transactions is a feature fo the combined set of components. If one does not play the game and is needed, the match is off.

I didn't do a good job of expressing my problem. It's not the case that you describe, where a component simply doesn't support transactions. It's the case where a contracting type would be expected to support transactions but doesn't because of impl limitations. For example, a DatasetGraph extends Transactional, but some DatasetGraphs really can't support transactions. My understanding was that that's the point where you bring in TransactionalNotSupportedMixin, to indicate that fact, and I was looking for the equivalent for TransactionalComponent. But maybe I am misunderstanding TransactionalNotSupportedMixin?

> I was looking at space used for the new parser caching but a side effect is a few preliminary timing figures.
> Here are updated figures for Jena latest with dexx 0.6, one run to warm up the JIT first.
<figures snipped>
> dexx 0.6 didn't make a noticeable different and it looks like TIM is acceptably slower and does not use much more space.
> 
> Now, whether there are optimizations in TIM that can bring down the time, is the big question.

Well, this may make JENA-1084 pointless, in the best possible way! Yes, I think there are optimizations available. How much they will do, I can't say with any certainty. But I can certainly start looking at them. The one that I would most like to work on would be the use of "mutate-in-place" extensions for the persistent data structures, but Dexx isn't contemplating that (it's basically a port of the Scala data structure library) and I'm not sure how easy it would be to "graft" that on. There's also the fact that ideally, we would like "in-place" to mean "in a transaction", but unlike Mantis, we don't yet have a real object that is the transaction. We're still letting threads stand in for that.

---
A. Soroka
The University of Virginia Library


Re: TransactionalNotSupportedMixin vs. Transactional vs. TransactionalComponent

Posted by Andy Seaborne <an...@apache.org>.
On 11/04/16 20:30, A. Soroka wrote:
> A separation was recently introduced by Andy between Transactional
> (application-side interface) and TransactionalComponent (system-side
> interface) interfaces, which I believe I understand and definitely
> support. Additionally, a TransactionalNotSupportedMixin interface was
> introduced in order to support "un-Transactional" behavior. It
> extends Transactional and provides default implementations for the
> methods in Transactional that throw UnsupportedOperationExceptions.
>
> My question: should TransactionalNotSupportedMixin actually be the
> "override" for Transactional (as it currently is), or for
> TransactionalComponent, or oddly, for both? Would it be more
> appropriate to introduce a new NonTransactionalComponent mixin or the
> like? I suspect that it would be, because we want Transactional and
> TransactionalComponent to be able to evolve with some real
> independence, but I also suspect that I am missing something here.
> {grin}

A "Transactional" is the client facing API for the whole set of 
components going to make the sub-system.

"TransactionalComponent" is what makes up "Transactional"s.  For TIM, 
they look quite similar because there is no worrying about stuff on disk 
or recovery.

A more complicated one is:

https://github.com/afs/mantis/blob/master/dboe-transaction/src/main/java/org/seaborne/dboe/transaction/txn/TransactionalComponent.java

where
1/ It's "begin(Transaction transaction)"

There is a  Transaction object and transactions are not tied to threads 
in the interface.  The transaction knows if it is R or W.

2/ A lot more operations that only make sense where:

startRecovery / recover / finishRecovery
commitPrepare / commit / commitEnd


I'm not sure what a component that does not offer transaction support 
would mean - either it's transaction oblivious, so does not need the 
interface, or its controlled by a component, in which case the 
TransactionalComponent-ness is elsewhere.  Transaction/non-transactions 
is a feature fo the combined set of components. If one does not play the 
game and is needed, the match is off.

E.g.
Every Java Map isn't a TransactionalComponent.

>
> (For context, this came up for me looking at JENA-1084 as I try to
> tease apart different kinds of behavior in the TxnInMem dataset impl
> and amongst them, transactionality. That impl uses a design wherein
> tuple tables, each for a particular order of columns, are coupled up
> into multiplex tables that can support all queries. So the question
> of how to correctly combine transactional and non-transactional code
> is practical. I started using TransactionalNotSupportedMixin to mark
> non-transactional implementation code, but now I'm confident that I
> was wrong and that the "override" for TransactionalComponent is what
> I really want, but it's not there! {grin})

I was looking at space used for the new parser caching but a side effect 
is a few preliminary timing figures.

Here are updated figures for Jena latest with dexx 0.6, one run to warm 
up the JIT first.

BSBM 5 million:

General/NoCache       Space=4209.16 MB  Time=30.93s
General/Caching       Space=1927.53 MB  Time=28.76s

TIM/NoCache           Space=4656.02 MB  Time=41.44s
TIM/Caching           Space=2374.39 MB  Time=38.21s

dexx 0.6 didn't make a noticeable different and it looks like TIM is 
acceptably slower and does not use much more space.

Now, whether there are optimizations in TIM that can bring down the 
time, is the big question.

	Andy

>
>
>
> --- A. Soroka The University of Virginia Library
>