3

I am trying to create a heavily modular and data-driven program in python, and I'd like to have calls between modules go through a central proxy singleton instead of every object holding references to objects they communicate with. The main reason for this is that I don't want objects to have any information of how other modules work in case they are switched around during runtime.

Currently, this proxy service is just a singleton that has a list of tuples with function names and a reference to the object that owns it. Any time a module comes across a command that isn't part of their own methods, the default behavior would be to send it up to this proxy service that would check is there is anyone online capable of executing it. If it finds someone, the proxy forwards the function call to the right object and then sends the return to the caller once it receives it.

The problem I have with this is that every time I need to do any inter-process communication, I am causing a context swap to an object that will end up bloating my callstack unnecessarily.

My question then is thus:

How are context changes such as this handled in python implementations? And what optimizations can I make to lower the impact of such context changes?

P.S.: The name proxy might be a bit misleading, but this is not a networked application. The whole thing is running in a single process in a single machine.

Edit: As asked here is a more concrete example.

class forwardToProxy:
       dict = {} #this dictionary would contain the names of commands such as "deleteName"
                 #and a first class function bound to the part of the program currently
                 #responsible for executing that command.

       def forward_command(command, arg):
           return dispatch[command](arg)

This is one example of what I meant for a proxy object. The only thing this class does is forward commands to the parts of the program currently assigned to executing. My question pertains to the consequences of using this kind of structure.

  • Does every call a module makes to it create a new instance of this class in memory until it resolves?

  • If a command were to be forwarded to a module, that would in consequence forward another command, and would cause another module to forwards yet another command, how many instances of this object would be waiting in memory for the eventual return?

  • What exactly happens in memory every time we make an function call in different python implementations?(Please explain for both same-module and external-module calls)

  • What optimizations can be used to reduce the impact of such context changes(would @staticmethod help, for example)?

Althis
  • 181
  • 6
  • 2
    would you like to post a minimal example? – georgexsh Nov 12 '17 at 16:55
  • 2
    Some extra explanation of the problem wouldn't go amiss, either. E.g. you mention inter-process communication, but later reveal that your application would run in a single process. Also, what is it that you want to optimize: just the depth of the Python call stack, or actual context switching in the interpreter? Or the impact of having to do a lookup before every function call? – David Nemeskey Nov 13 '17 at 11:19
  • I don't see a lot of stack overhead in your design - it's not recursive or smth. Instead of one direct call, you first call the proxy and then the proxy calls the actual implementation - so it's two function calls instead of one. No big deal in terms of stack usage for me. – Grisha Nov 15 '17 at 15:11
  • Maybe I'm totally missleading. But couldn't you store your output in a queue which uses a trace exchange with a fan. Then the sending could be one process while the next task could be processed by the same worker. This can also be done locally using eg. rabbitmq server. The overhead could be decreased using mutliple workers that share the same task or are able to process multiple tasks. – Max Krappmann Nov 16 '17 at 16:55
  • What "context swap" are you talking about? Your example code shows a simple dictionary mapping strings to functions. I get that client code can use an instance of this little class to call a function without knowing in what module that function is defined. That might be useful, but your program must still load all the modules it needs to populate the dictionary's values. You seem worried that there's some performance issue when the functions are defined in several different modules, but there isn't. A module is just a file with some code in it, not a separate execution context. – Paul Cornelius Nov 19 '17 at 07:38

1 Answers1

1

Interesting topic. Frankly speaking Python is not expected to work fast, however, I observe more and more demand on that.

In short:

Function scope is a dict, and can't see much to optimize here.

A bit longer explanation:

I know that named tuple is used when space optimizations come to play. The reasoning is that with named tuple all keys are the same, and kept once. That way you can save some space in the proxy definition. However, if you call function, it creates a scope, which is dict. That is how Python works. How to optimize it? Well, you have to write that in C, to have full control over what, and when is allocated.

Community
  • 1
  • 1
Michał Zaborowski
  • 3,911
  • 2
  • 19
  • 39
  • Hello, this could be used as some kind of source: https://stackoverflow.com/a/100146 – MEE Nov 19 '17 at 10:58
  • In Python everything is an object. Object itself, class, meta class, as well as function / method. If there is singleton proxy, then class / meta class are not relevant here. For method / function - each call creates scope, which is dictionary. Each key is variable name, and value is it's value. That can't be done in different way inside Python. – Michał Zaborowski Nov 19 '17 at 13:33
  • I supposed this could be a `credible` source (bounty) – MEE Nov 19 '17 at 14:03
  • I was looking to reference something, but that was easier to write down what I know. Also I'm just interested in understanding 50 pts. bounty is not that much - accepted answer gives 25. – Michał Zaborowski Nov 19 '17 at 14:36