[Bf-committers] Python Access to some properties of nodes

Bartek Skorupa (priv) bartekskorupa at bartekskorupa.com
Sat Dec 22 11:39:30 CET 2012


Thank you very much Lukas.
Access to NodeSocket.links may be very helpful and if I had this earlier, I'd probably design my code in: http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Nodes/Nodes_Efficiency_Tools a bit differently.
I am especially talking about the operator: NODE_OT_switches_to_outputs.

However now after your explanation I begun to wonder if it's not just "hiding" the process from the coder.
Let me explain:
In my code I wanted to do some operation depending on links connected to outputs that I specified. So in fact I am referring to NodeSocket.links.
Because I didn't have direct access to it, I knew that I have to iterate through all of the links.
Iterating through all links for all of the outputs seemed not right for me, because I assumed that list of links will in most cases be longer than list of my "selected" outputs.
Therefore I wrapped loops the other way, i.e have just one loop "for links" and analyze all my sockets inside this loop.

# code A
for link:
    for socket:
"do the magic"


instead of 

# code B
for socket:
    for link
"do the magic"

This was more difficult in my case, but doable. If I had the access to NodeSocket.links, I'd probably not think about it and would simply do:

# code C
for socket:
   for socket.links
"do the magic"

Easy, but isn't it so that accessing NodeSocket.links does iteration through ALL links anyway under the hood?

The question is:
From performance point of view: doesn't code B require exactly the same amount of computing as code C?
Or maybe because NodeSocket.links is shorter than all links - it's faster.
Does it even matter? Maybe I try to fix the issue that doesn't exist?



Bartek Skorupa

www.bartekskorupa.com

On 22 gru 2012, at 08:21, Lukas Tönne <lukas.toenne at gmail.com> wrote:

> IMHO storing the links in a separate list like we do now is one of the
> more well-designed code parts ;)
> 
> It may be slightly inconvenient if you want to get a list of links for
> a specific socket, but it has several advantages over storing lists of
> links in each socket or node:
> 
> * If each socket stores its own link list that means a lot more
> overhead for all those lists. Now we have exactly 1 list.
> * You only ever need a single loop. If each socket has a list of
> links, to walk over all links in a node tree (e.g. for drawing or the
> cut operator) you need to walk over all nodes and then all sockets and
> then all links ...
> * Storing a link in sockets is ambiguous, you could store the link
> either in the output or input socket. If you store it on one side only
> you have to loop over everything again to find links of the other
> side. If you store it in both you have to keep them in sync, which is
> error prone and leads to redundant data.
> * In terms of time complexity having to filter the list of all links
> vs. a reduced list of socket links does not make much difference, both
> are essentially O(N+M), where N is number of nodes, M is number of
> links. In general though the node DNA should not be judged by
> performance criteria too much, if you need to access the node
> structure millions of times (e.g. in rendering) you should create an
> optimized structure with arrays instead of linked lists and can store
> links in whatever way is needed for fast access. All modern node
> systems in Blender (cycles, compositor) do this.
> 
> Bottom line: the single links list is the best all-round solution for
> the purpose of storing data in .blend files and user manipulation.
> 
> On Sat, Dec 22, 2012 at 2:49 AM, Dan Eicher <dan at trollwerks.org> wrote:
>> On Fri, Dec 21, 2012 at 4:52 AM, Lukas Tönne <lukas.toenne at gmail.com> wrote:
>> 
>>> # List of connected (Node, NodeSocket) pairs for 'socket':
>>> input_sockets = [(link.from_node, link.from_socket) for link in
>>> socket.id_data.links if link.to_socket == socket]
>>> output_sockets = [(link.to_node, link.to_socket) for link in
>>> socket.id_data.links if link.from_socket == socket]
>>> 
>> 
>> Somewhat off topic...
>> 
>> Looking at this code I'm starting to think that maybe it was a mistake to
>> expose Node.links instead of having it as a property on the sockets
>> themselves, it would make the code a lot clearer and it isn't like you can
>> really do anything with the links independent of the sockets they're
>> assigned to.
>> 
>> It may even be better to totally abstract away the NodeLinks too, maybe
>> socket.links just return a list of (Node, NodeSocket) tuples -- have to
>> think on this a bit more though since it would probably require
>> sub-classing NodeSocket into NodeInputSocket, NodeOutputSocket so you'd
>> know if the returned node/socket pair was an input or output for the node.
>> 
>> Would also clean up node.links.new(add?) a bunch.
>> 
>> Dan
>> _______________________________________________
>> Bf-committers mailing list
>> Bf-committers at blender.org
>> http://lists.blender.org/mailman/listinfo/bf-committers
> _______________________________________________
> Bf-committers mailing list
> Bf-committers at blender.org
> http://lists.blender.org/mailman/listinfo/bf-committers



More information about the Bf-committers mailing list