[GRASS-dev] [GRASS GIS] #2134: Create a general exit-safe interface to C libraries
GRASS GIS
trac at osgeo.org
Tue Nov 19 04:19:29 PST 2013
#2134: Create a general exit-safe interface to C libraries
--------------------------------------------------+-------------------------
Reporter: wenzeslaus | Owner: grass-dev@…
Type: enhancement | Status: new
Priority: normal | Milestone: 7.0.0
Component: Python ctypes | Version: svn-trunk
Keywords: G_fatal_error, exit, multiprocessing | Platform: All
Cpu: Unspecified |
--------------------------------------------------+-------------------------
Comment(by huhabla):
In my opinion the RPC approach is only meaningful for persistent
applications that need fast access to C-library functions, or that need
low level API access for data modification (like digitizing).
My intention to write the RPC server was to make the temporal framework
usable in persistent applications and to be as fast as possible.
Extending the PyGRASS framework with signal handling will not solve the
problem: that memory structures may be corrupted in case of a
G_fatal_error() call or a segfault, leading to incorrect computation
results or to segmentation faults in the persistent application.
Implementation of persistent applications that use the GRASS C-library
functions in their process memory is IMHO not possible. We have had this
discussion for years.
The PyGRASS interface is well designed for module programming not for
persistent applications. Otherwise each C-function call should be handled
via RPC. From my point of view and some tests that i made slows the RPC
approach the processing significantly down.
Example:
{{{
from multiprocessing import Process, Pipe, Lock
import time
num = 50000
def func(a):
b = a + 1
c = b + 1
d = c + b
return d
# DICT
def dict_func():
a = {}
for i in xrange(num):
a["%i%i%i%i"%(i,i,i,i)] = func
start = time.time()
for i in xrange(num):
a["%i%i%i%i"%(i,i,i,i)](5)
end = time.time()
print end - start
def target(lock, conn):
a = [func]*num
while True:
# Avoid busy waiting
conn.poll(4)
data = conn.recv()
lock.acquire()
ret = a[data[0]](data[1])
conn.send(ret)
lock.release()
def rpc_func():
client_conn, server_conn = Pipe()
lock = Lock()
server = Process(target=target, args=(lock, server_conn))
server.daemon = True
server.start()
start = time.time()
for i in xrange(num):
if server.is_alive() is True:
data = [i, 5]
client_conn.send(data)
client_conn.recv()
end = time.time()
print end - start
if __name__ == "__main__":
# Measuring the time to call of 50000 functions that are
# registered in a dictionary
dict_func()
# Measuring the time to call 50000 functions
# using an RPC approach
rpc_func()
}}}
Running the script will show that calling functions from a dict is 50 time
faster than using a pipe with a subprocess.
{{{
python rpc_test.py
0.0984511375427
4.59985399246
}}}
--
Ticket URL: <http://trac.osgeo.org/grass/ticket/2134#comment:7>
GRASS GIS <http://grass.osgeo.org>
More information about the grass-dev
mailing list