Awasihba’s Log

October 29, 2008

Create Proxy function in perl

Filed under: programming — Tags: — abhisawa @ 6:38 am


Almost every time when you get handover of someone else code, before you crawl thorough all its hairy functions and figure out to which database tables they are scratching, your manager comes and ask for some enhancements in it with stringent deadlines. If your functions are working like blackbox, means for particular set of inputs always returns fixed type of outputs then here is way to extend functionality of any function in perl.

I will use this kind of functionality to maintain my own cache on top of someone else code to make code run faster. All this possible because of access to symbol tables in perl. So symbol table is hash like structure which holds all the the typeglobs in that particular namespace, and typeglob is key and value pair structure with limited set of keys like SCALAR, ARRAY, HASH, CODE,GLOB,FORMAT,IO where each key have value as reference of data for particular variable type. Its very short definition of symbol table and typeglob, to understand it better ask for help from your friend called internet.

All subroutines in program are global that means you can always find their reference in symbol table that means you can not define subroutine with ‘my’ ( actually you can attach ‘my’ variable to anonymous subroutine reference , but we are not going to consider that over here ). The trick over here is about pulling out reference of original function from symbol table and wrap it under your customized function. Then update symbol table with reference of your wrapper function which internally calls original function with its magical overheads.

Take a look at following example code, in this exercise we are going to steal reference of subroutine named my_function() which prints one statement with all input arguments. On line 6 we are stealing and replacing my_function() with help of subroutine called Proxy() which is imported from package named PROXY.pm.



example.pl

#!/usr/bin/perl
#
use strict;
use PROXY;

Proxy 'my_function';

sub my_function {
  my @input = @_;
  print "This is original my_function and inputs are ";
  print "@_\n";
}

&my_function ("one two three");

So subroutine Proxy() takes subroutine name as an input argument, it generates full name of that subroutine with namespace part attached on line 11 in following code. Once it gets to that it steals reference of that particular subroutine from symbol table on line 14 . On line 16 with help of selective aliasing it replace that subroutine reference with another reference.

Now new reference is pointing to anonymous subroutine which returns a closure having subroutine named Stub() getting feed with original function’s reference ( i.e. my_function() reference ) and its input arguments. Stub() should be designed to do whatever you want to do prior the execution of original subroutine. On line 24 it prints extra line and then calls my_function() along with its arguments.



PROXY.pm

package PROXY;
use strict;
use Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw( Proxy );

sub Proxy {
  my $function_to_steal = shift;

  my $who_called = caller;
  my $function_name =
    $who_called . '::' . $function_to_steal;
  no strict;
  my $function_referance = *{$function_name}{CODE};

  *{$function_name} =
    sub { &Stub($function_referance,@_); };
}

sub Stub {
  my $original_function = shift;
  my @input = @_; 

  print "This is originating from stub function\n";
  $original_function->( @input );
}

In the output when you called &my_function(“one two three”) in example.pl, it will following two lines instead of only one line.


Output

This is originating from stub function
This is original function and inputs are one two three

You can enhance Stub() for your own devious purpose like I mentioned to maintain local cache of some expensive database queries.

reference
Above code is very basic version of Memoize.pm by Mark-Jason Dominus

October 13, 2008

UDP on freebsd

Filed under: freebsd, udp — Tags: , — abhisawa @ 1:32 pm

My recent encounter with UDP packet drop on freebsd boxes gave birth to this post. Here what I learn from that skirmish.

Why UDP needs tune up as compare to TCP ?
Operating system automatically assign TCP buffer space on based on different factors, and TCP sending kernel can monitor buffer flow adjust sending size of data with help of window scaling. These kind of facility is not availble for UDP.

Buffer space for any UDP connection on freebsd is affected by following parameters

net.inet.udp.recvspace – When you open any UDP socket this parameters decides default receiving buffer space for userland data for that socket . You can override that size with help of setsockopt in your code.

kern.ipc.maxsockbuf – The buffer space for whole socket is determine by this parameter. So if you try to open socket with large send and receive buffer and you get error like ‘no buffer space availble’ then you should consider tweaking kern.ipc.maxsockbuf. Sometime you see frequent UDP drops while dealing with large number of tiny UDP packets. Even if your recvspace buffer is not filled up completely , still you will drop the packets. After digging around for a while we figured out that it was happening because we were hitting another hard limit of sockbuf->sb_mbmax, it specifies maximum number of mbufs allocated for each socket. You can increase that limit by increasing kern.ipc.maxsockbuf . You need to restart related services to get advantage of increased

kern.ipc.nmbcluster – this parameter governs ultimate amount memory you have to allocate all sockets opened on that system. This number tells how many number of mbuf cluster should be allocated. Usually each cluster is of 2k size. For example , if you are planning to open 1000 sockets with each having 8k sending and 8k size receving buffer . In this case each socket will need 16k of memory and in total you will need 16M (16k x 1000 ) of memory to handle all 1000 connections.

Blog at WordPress.com.