Hi everyone,
I am a hardcore C/C++ programmer and have been using perl for the past few weeks/months.
In our new company, the server side is mostly written in perl. The server side code mostly uses the DBI module to connect to the database, query it, get the results and dispatch those results off to the UI.
Several of the server side modules lie directly in the path to the database. Sometimes, the database queries can fail. Recently, we encountered "mysql deadlocks". Our perl subroutines would just die (or worse yet, could totally ignore the database failures). My task was to catch the database failures and propagate them to the level where the UI would pop up a window for the user.
I decided to go with the try-catch-throw pattern in perl. We are also using Error::Simple (I understand it's deprecated, but nevertheless, that's the practice as of now) to throw and catch the error.
Now, let's say I have a module with several subroutines. Some of the subroutines are "interface functions" that are calling the internal subroutine functions (static function equivalent in C).
Let's say I have one interface function and 2 internal subroutines. Let's say each subroutine can fail somewhere and throws an error. The job of the interface function is to "try" the subroutine, catch the error, and throw the same error, so another interface function that's calling this one can catch it. This chain eventually propagates all the way to the UI.
sub interface_sub { try { internal_sub1($arg1, $arg2); } catch Error with { my $E = shift; throw Error::Simple($E); }; try { internal_sub2($arg1, $arg2, $arg3); } catch Error with { my $E = shift; throw Error::Simple($E); }; }
To reduce the code and make it look better, I decided to call all internal subs using a function reference.
sub exec_internal_sub { my ($sub_ref, @sub_args) = @_; try { $sub_ref->(@sub_args); } catch { my $E = shift; throw Error::Simple($E); }; } sub interface_sub { exec_internal_sub(\&internal_sub1, $arg1, $arg2); exec_internal_sub(\&internal_sub2, $arg1, $arg2, $arg3); }
This code ran fine.
However I got a review from one of the members saying that adding references and dereferences like this can have "serious memory consequences" in perl. He argued that perl is an interpreted language, and all functions are simple strings in memory until we call functions using references. When we add references, now there is a runtime lookup of that function and this can get complicated when the list of arguments is too long.
I did not completely understand what was being talked about here. The concept of a function pointer in C/C++ is simple enough to understand. All functions are accessed by their memory location and passing by pointer adds only 1 lookup operation. Since perl is interpreted, is this somehow different? Are there more penalties I am not aware of?
In my understanding, the perl program is loaded in memory, so calling each function even without a reference should still occur by using the function's address in memory. Passing a reference would just add one more lookup in the operation without any additional cost. I would like to know if I have totally misunderstood perl.
Finally, what's the cleanest way (aesthetically pleasing, not bleeding eyes) to implement try-catch-throw in the situation I have described above?
In reply to Cost of passing function references by sportsfan33
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |