Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Performance, Abstraction and HOP

by pg (Canon)
on Aug 31, 2005 at 21:18 UTC ( #488230=perlmeditation: print w/ replies, xml ) Need Help??

Performance

Is performance important in today's programming or is it no longer or rarely important any more? My answer is yes, performance is important, and it is always one of the most important measurement of the quality of your application. But its face is a little bit different now, and people no longer spend days just try to reduce the number of multipler in some math formular, as they do in the past. If one says that performance is not important, he is probably saying that he already gets enough performance, otherwise he is wrong.

The real question is not about whether you need performance, but how fast is fast enough, or whether the slowness is acceptable.

For example, I recently wrote a piece of Perl script to resolve Sudoku Puzzle. It took the first version more than half minute to resolve one puzzle. I didn't like that and thought that was too slow, so I tried to find different ways to improve it, and it ended up only took 1 second to resolve a puzzle. At that point, I knew there are still tweaks there that I can apply, but I said to myself, NO I am not going to change the script any more, as 1 second is fast enough, 0.5 second is faster, but 1 second is good enough.

Another example, in the company I work for, we have a piece of code that builds truck load, which must complete in 30 minutes. That is required by the business process, if the program doesn't complete within 30 minutes, starting from the 31st minute, we will have to pay truck drivers and other labours money even though they are doing nothing other than waiting for the computer to finish its job - so we are losing money. The program was in c, recently a guy changed it to Java, and it became slower and slow enough to pass the 30 minutes deadline. The whole team was threw in a big trouble.

So performance is important. If you are not under pressure to improve performance, it is not because that you don't need it to be fast, but because that it is fast enough. (Of course, it could also be that you are not good enough, you don't have enoguh time, or you are lazy enough.)

Abstraction

Now comes the second part: abstraction was never meant for performance. Abstraction was meant to make programmer's life easier. If you do the abstraction right, most likely you got more reusable code. (Side note: reusable code is not always reused. Other than some core components, the rest are never really reused, and people probably even don't know their existance. Donesn't matter what language we are talking about.)

The evil side of abstraction is the performance hit that usually comes as a twin. The good things are never good in all sense. At the beginning, abstraction is more important than performance, and OO programming opened up a new world where abstraction was made possible and much easier. Years passed, and lessons are learnt, and now people started to realize that they are forced to seek a balance point between performance and abstraction. As the most commercially successful OO language, Java world had the longest history that allows its citizens to learn the most valuable lessons in this area, and changes are being seen is the lastest Java versions and chatting in that world.

Perl is a comparatively new comer to the OO world, so not enough experience (positive and negative) has been accumulated, and lessons learned in other languages take time to spread to Perl world, and even not always welcomed. Perl is still continue its journey into deep (deeper)abstraction...

HOP

Now comes HOP. It is too early to comment on HOP in general, but one warning sign I can see is that: Higher Level could mean lots of things, but one of them is more abstraction. Slow is not slow, until you realize the slowness. Higher level of abstraction might soon tell us the other side of the story (than just the bright side it is supposed to tell).

Take Stream.pm as one example, its slowness should ring the bell.

A program can be fast enough that you no longer want to pursuit more speed. In the same sense, one day, people will realize that enough abstraction has been gained, and further abstraction is not practically needed.

It is a curve, at the beginning, the usefulness of the code is growing with its level of abstraction, but once it passes a point, the highly abstracted code is no longer useful, and you always need to write you specific code to patch them, and start to doubt whether you should move away.

Comment on Performance, Abstraction and HOP
Re: Performance, Abstraction and HOP
by Tanktalus (Canon) on Aug 31, 2005 at 21:37 UTC

    A pedant, perhaps, but an important one to me. Performance doesn't matter. Never has, never will. Responsiveness is what matters. Often one must improve performance to get responsiveness, but performance is never important of itself.

    For example, if you have some sort of server (whether that be web or otherwise) which can handle 1000 actions per minute, and then you improve the performance to 2000 actions per minute, you've no doubt improved performance. But if there are only 500 actions to perform per minute, then those 500 actions are unlikely to have had a resultant boost in responsiveness. And you've just wasted a bunch of effort. However, if you sometimes have a peak of 1500 actions to perform per minute, then that increase in performance will ultimately mean better responsiveness during that peak.

    I don't care that it takes my word processor 1.5 million or 1.5 billion cycles to handle the typing of 5 characters - I have 3 billion cycles per second, the responsiveness of the system won't suffer.

    What does that mean to abstraction? Lots. It means that if the system is still responsive when I use more abstraction, then I can save money on programmer time, which will make my system cheaper (theoretically, this would allow the program to be cheaper to produce, either meaning layoffs or more time-enhancing features for the same cost).

    You do need to be aware of responsiveness. For example, let's take a database at a bank. It's critical that everyone standing at ATMs, whether your own or your competitors in the same network, can access their cash within a couple of seconds. Most of this time is eaten up by latency, so fast data retrieval is of utmost importance. Yet, the overnight daily summaries given to the executives can take 6 hours to complete and be perfectly responsive.

    The biggest difference in my mind between performance and responsiveness is the focus. Performance focuses on code, computing, and programmers. These are always the wrong things to focus on. Responsiveness focuses on customers and users. These are always the right things to focus on. Rather than saying, "I need to get 2000 actions per minute", you need to say, "I need to ensure I can get all 1500 users each minute, at peak volume, their information calculated within 2 seconds of their request." And on the topic of databases, there are tools available to ensure different queries get different priorities to ensure time-critical get more system resources than large reports - I know IBM has their own DB2-branded version, and am guessing that other vendors either have their own, too, or third-parties are providing them. But it's an idea that is focused on the right area: applying the system to the right job at the right time. Focusing on responsiveness, not performance.

      Lots of applications today are interactive, and for those applications, peformance is mainly measured by the response time. One thing we have different idea is that, I don't see responsiveness as something different from performance, but rather one way of measuring performance. Other than that, we are mostly on the same page.

      I agree in part, but I think this is too narrow a view of what "performance" means or should mean. In my opinion, performance is multi-dimensional and it can only be defined from the point of view of the user/customer/business. That is where focus is critical.

      Reponsiveness is merely one kind of performance measure. Another measure might be agility or adaptability (e.g. the turnaround time for necessary changes to the codebase to be rolled into production). This matters for things like new product development where new products have large impacts on existing systems and processes and time-to-market is critical for competitiveness.

      From that perspective, if agility is one of the performance metric, then abstraction may be a useful tool at incresing agility, despite a cost in responsiveness. Or at least, improvements in agility must be traded off against costs in decreased responsiveness. Other metrics might include ongoing maintenance costs, which again might mean a different tradeoff between speed of execution and abstraction.

      People shouldn't get so caught up searching for a nail for their hammer, whether that's "efficiency" or "abstraction". There is no one universal tool -- it takes a whole toolbox, properly applied to the task at hand, to deliver a valuable solution.

      -xdg

      Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      This is only true if you can hog the system. Application programmers often fall into the dangerous mindset of believing that their application is the only thing that matters and therefore it is ok to e.g. temporarily use all the memory a current machine can reasonably be expected to have.

      Every single machine I've worked on for the last 15 years runs multiple independent applications at the same time, regardless whether this is a server or desktop. If one of the apps consumes an undue amount of system resources to the detriment of other apps, I'll be keen to look for an alternative. In the context of your post, if your app can now performs 2000 actions per minutes as opposed to 1000 actions before, it is highly likely that the 500 required actions will be performed using less system resources than before and this can be worthwhile although there is no measurable change in responsiveness.

      So IMO performance does matter beyond responsiveness requirements if you consider resource consumption per action an element of performance. All the usual caveats (premature optimization is the root of all evil, profile before you optimize, developer time vs.optimization gains etc.) apply, of course.

        I see this, too. The billing mediation server at our telecom company is powerful, but runs so many applications that it can get backlogged... and backlogs can be dangerous when data keeps rolling in.

        Of course, the main reason we have a backlog is because we invoke multiple Java Virtual Machines. So then, poor responsiveness is due to poor environment or design considerations, or something like that.

        Now, the operations guys tell us that if perl was the runtime chosen, there would have been no backlog. But apparently, Perl isn't Buzzword Compliant :(
      There was a study done several years back that determined that, if a given program took more than X seconds to respond to user input, it was considered "slow" regardless what was happening behind the scenes or how fast the program actually was. Because of this perception, calculation intensive programs like spreadsheets are so that the information that is currently displayed is recalc'd immediately. The rest of the spreadsheet (the part that is not currently displayed) is recalc'd as a background task. Similar gymnastics are done with indexing on interactive database programs, repagination in word processor, etc.

      So, the program appears to be faster - and more responsive - than it actually is.

      Just some food for thought.

      Jack

Re: Performance, Abstraction and HOP
by Ovid (Cardinal) on Aug 31, 2005 at 21:46 UTC

    I think you'll agree with what I'm about to say, but I think it's an important point to reiterate.

    You wrote: ...performance is important, and it is always one of the most important measurement of the quality of your application.

    In a paper defending the virtues of goto, Knuth wrote about looking forward to the day when computers were fast enough that performance is no longer such a critical concern. Interestingly, his comments relate to yours in two different ways. He was making it clear that performance a necessary consideration but, more importantly, he was directly addressing the "never use goto" dogma that had arisen. (As a third point of relevance, I got that link from the HOP mailing list).

    The problem with the dogma was fairly simple: by using "always" as the criteria, one was sometimes forced to go to extreme lengths to avoid goto and this could cause performance issues. In your case, you state that performance is always one of the most important considerations. I tend to disagree.

    Admittedly, there are certain classes of problems for which performance issues must be addressed up front. Ray tracing programs are rarely written in Perl. In this case, a better solution that figuring out how to improve the performance of your favorite tool is to figure out the most appropriate tool for the job. C or C++ are going to be big wins here.

    If I am forced to pick a "most important" measure of quality, I would argue for program completeness and correctness. In other words, the program should correctly do everything that it is supposed to do and do nothing it's not required to do. Once you have correctness and completeness down then, if performance is still an issue, profiling should be considered.

    Sometimes performance is gained by coupling things that shouldn't be coupled, denormalizing the database or writing an obscure algorithm. However, if someone is doing that up front I'm going to be pretty unhappy if they've tripled the speed of a function that only uses two percent of the total program run time. Frequently when programmers guess where the performance problems will be they guess wrong. Thus, by worrying about performance before we worry about correctness and completeness, we're more liable to build overly complicated and confusing code. What's worse, that confusing code is less likely to benefit our overall performance.

    Performance is often important, but it should rarely be the first consideration. If we avoid useful (a carefully chosen word) abstractions out of fear they will slow things down, we're hurting our ability to write correct and complete code. Focus on performance after you know the code is right.

    Cheers,
    Ovid

    New address of my CGI Course.

      I agree in principle with most of what you've said, but there are a few qualifiers that I would add:

      If I am forced to pick a "most important" measure of quality, I would argue for program completeness and correctness. In other words, the program should correctly do everything that it is supposed to do and do nothing it's not required to do. Once you have correctness and completeness down then, if performance is still an issue, profiling should be considered.

      In some cases, such as real time programming, responsiveness is completeness. It's no help to have the brakes activate with the optimal number of newtons of force after the car has already hit the tree. It's better to have a "wrong" solution that applies the brakes a bit too hard or too soft than too late.

      Focus on performance after you know the code is right.

      In practice, this is easier said than done. What if the fundamental data structures and design decisions are the inefficient part? If the design gets too abstract, this can happen. I've seen it happen many times in the past.

      Whenever you need to change the fundamental assumptions of a program, you're either looking a massive refactoring project, or possibly even a total rewrite. Just try telling management that the expensive new program you spent months writing for them is too slow and needs to be totally redone from scratch. That's pink slip territory for a lot of us.

      Sometimes, it's better to design efficiently in the first place, and worry about abstraction later. It's nice to solve problems that you might not have, but a clean design that solves your current problem might well be smarter and cheaper in the long run.
      --
      Ytrew Q. Uiop

Re: Performance, Abstraction and HOP
by hv (Parson) on Aug 31, 2005 at 22:17 UTC

    I have a different viewpoint: abstraction can be an aid to performance.

    Here's an example: the perl interpreter is written in C, yet for many string matching tasks, perl's regular expression engine is faster than hand-crafted C code. That sounds like a contradiction, but for most tasks the speed of string matching is not worth spending several man-years of development time on. Every time you use the regexp engine, you are leveraging the many man-years of development that have gone into making it fast.

    Regular expressions (and the irregular extensions available in perl) are an example of an abstraction that gain you performance by letting you use someone else's work. The better the abstraction, the more widely applicable it is, the more benefit stands to be gained.

    And by using abstractions that hide the gory details of highly optimised code, it frees up my precious development time to find performance wins in other parts of the code, or to write a Sudoku solver.

    Hugo

      I completely agree with you, with one caveat. The abstraction has to be well designed and well optimised. Perl's regex engine is a great example of abstraction done well.

      A counter example is trees & tries. These are immensely useful structures for many purposes, and there are quite a few flavours of both on CPAN. But, for the most part, they are almost useless for anything but experimentation and the most trivial of applications. They are, mostly, based upon using hashes to construct the trees, with the result that the are slow, clumsy and hugely memory hungry.

      Basing my opinion only upon the little I have read here and elsewhere, not yet having succeeded in laying my hands on a copy of HOP, the main problem with the style of coding it explores is that Perl isn't sufficiently tuned for it. To see the problem, take a look at this HOP-like implementation and constrast it (performance-wise) with procedural implementation of solutions to the same problem.

      That's not to say there isn't a lot to be learnt from the concepts explored in HOP, just that the costs of sub calls, coderefs and recursion in Perl 5 do not lend themselves to this type of programming where performance is a consideration.

      And not all Perl apps are web applications, DB or IO bound, or otherwise "interactive" where performance can be measured in response times.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.

        I think that we are on the same page. I am from the Java world, and in most of cases, Perl's level of abstraction is well below the level I can accept. Abstraction is not a problem to me in general, but a flag is raised when you see the performance of some HOP-like programs. Doesn't matter how important one think performance is, or what the definition of performance is, when it becomes too slow and not practical any more, that's where you start to worry.

        I completely agree that Perl is not tuned for certain things.

        A side note, I believe that for Perl to survive the war of languages, the real winning point is "application areas". For example, Perl was once considered the language for CGI, and that's when Perl had its most glorious time. This position is no longer there for Perl, and I see Perl's hope in the future as to re-establish its position in certain application areas, not anything else. When people pick languages, I don't think they will pick Perl because of HOP.

        Did Java reach its position today because of the nice OO idea, yes but not mainly. The main reason was that it was perceived as the networking language for application areas like "internet" and "intranet" (Perception), and the strong killing will of Microsoft's rivals (Politics and Money) ;-)

        A counter example is trees & tries. These are immensely useful structures for many purposes, and there are quite a few flavours of both on CPAN. But, for the most part, they are almost useless for anything but experimentation and the most trivial of applications. They are, mostly, based upon using hashes to construct the trees, with the result that the are slow, clumsy and hugely memory hungry.
        I'm guessing that you mean that tries are implemented with hashes. I can't image trees implemented with arrays being that much more memory hungary than arrays alone. Sure, operations on trees will be slower than similar operations on arrays, but that's mostly comparing perl vs. C.
        #!/usr/bin/perl -w use strict; use Data::Dumper; my $MAX = 10000; my $tree = make_tree($MAX/2,undef,undef); for(my $x=1;$x<$MAX;$x++) { $tree = insert(int(rand($MAX)), $tree); } print "sum = ", sum_tree($tree), "\n"; #print Dumper $tree; sub sum_tree { my $tree = shift; return 0 if not defined($tree); return node($tree) + sum_tree(right($tree)) + sum_tree(left($tree) +); } sub insert { (my $elem, my $tree) = @_; if(not defined($tree)){ return make_tree($elem, undef, undef); } my $curr = node($tree); if( $elem == $curr) { return $tree; } elsif($elem < $curr) { return make_tree($curr, insert($elem,left($tree)), right($tree)); } elsif($elem > $curr) { return make_tree($curr, left($tree), insert($elem,right($tree))); } } sub make_tree { [$_[0], $_[1], $_[2]] } sub node { $_[0]->[0] } sub left { $_[0]->[1] } sub right { $_[0]->[2] }
Re: Performance, Abstraction and HOP
by perrin (Chancellor) on Sep 01, 2005 at 03:33 UTC
    Are you sure you mean HOP? Higher-order programming has to do with using functions as arguments, not with more abstraction or "higher level" anything. You might have more abstraction when using these techniques, but not necessarily.
Re: Performance, Abstraction and HOP
by samizdat (Vicar) on Sep 01, 2005 at 13:50 UTC
    What a thoughtful meditation, pg. Thanks to you, and also all the followup posters.

    Performance means many things. When you are dealing with outside influences, be they characters coming in on a serial port or user keystrokes, responsiveness is the key measure of performance. In 'hard' real time programming, people can die if your program is not fast enough to handle its inputs.

    Most of our programming is not so critical. As has been pointed out, web servers rarely need do much more than yawn to keep up with the bandwidth of their pipes. Likewise, having an entire UNIX machine with gobs of memory and CPU cycles to one's own self does tend to make one complacent when it comes to CPU-oriented performance tuning. As has already been said, we really do need to make our programs polite enough not to hog the machine where community usage is the case.

    All that aside, I'd like to argue for abstraction for another kind of performance. Many times, I write programs that are used to analyze data produced somewhere else. Often it's the case that the data changes and also the input formatting changes from run to run. Performance and responsiveness, in this case, depend on me as the programmer being able to whack the code into a new shape quickly and correctly.

    Likewise, team programming depends on abstraction to protect the members' code chunks from each other. While Java has its faults, team performance (as in productivity) is likely to be better in a Java shop than in a Perl shop.

    That's not to say that it isn't often the case that one Perl programmer
    can outdo an entire Java shop, but that's another meditation!
Re: Performance, Abstraction and HOP
by Dominus (Parson) on Sep 01, 2005 at 14:08 UTC
    pg says:
    Take Stream.pm as one example, its slowness should ring the bell.
    Slow compared to what? For what purpose?

    I want to say that I don't think that Stream.pm is "slow". But I don't know what you think you mean, so I cannot contradict you. After three years of teaching performance tuning classes at OSCON, the one thing I am sure I have learned from my research is that people are much too eager to say it's "too slow" when they don't really know what they mean by it.

    For example, you might mean that it is slower than using arrays. But it doesn't do the same thing as arrays, so there is no reason to expect it to be as fast as arrays. Perl arrays are slower than C arrays. This is not a defect in Perl arrays. Perl arrays were not supposed to be as fast as C arrays; they were supposed to support push.

    Another thing I learned from my research for the classes is that people pronounce things "slow" or "fast" without doing proper research, and with no regard for the real facts. Even when they do the research, benchmarking a tricky business. The tools are bad, and they are easy to misuse. One whole section of my class is nothing but examples of benchmarks that were written incorrectly and led the writer to the wrong conclusion. Some of those examples come from Perlmonks.

    One more point occurs to me. This is that the techniques in my book are primarily based around using functions. If the techniques are slower than other techniques, it is probably because they call a lot of functions. If function calls are slow, that is not a problem with the techniques; it is a problem with the language implementation. Function calling is not a frill that you can avoid when you want extra speed; it is essential. Every program makes lots of function calls. Avoiding function calls because they are slow is an absurd response to performance problems. If Perl's function calls are slow, the right response is to try to fix the implementation, not to try to avoid function calls.

      If Perl's function calls are slow, the right response is to try to fix the implementation, not to try to avoid function calls.

      As someone with more than a passing familiarity with the internals of Perl 5, do you consider it feasible* to substantially improve the current performance of function calls?

      Update: *Given the nature of the forum, perhaps practical is a better word than feasible in this context.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
        BrowserUk asks:
        Do you consider it feasible to substantially improve the current performance of function calls?
        Sorry, I do not have an informed opinion on that topic.

      If Perl's function calls are slow, the right response is to try to fix the implementation, not to try to avoid function calls.
      Or, if you can try the hybrid approach, and eat your cake as well as have it...
      But, if you study programming languages, you discover that although there is a problem, through a small number of correctness-preserving transformations, this problem can be averted. And by being aware of the problem, you can better appreciate the merits of languages that manage to avoid it.

      Do your home work before you came here with flame. Do a super search, and you will find the OP did tested Stream.pm's performance Streams and "deep recursion" warning.

      The moment you put your module on CPAN, is just like the moment you entering a recruit office, you should expect what is in front of you. People will comment your module, good or bad. Go improve your module, before you start to be defensive. The truth is that that module is quite useless.

      One more point occurs to me. This is that the techniques in my book are primarily based around using functions. If the techniques are slower than other techniques, it is probably because they call a lot of functions. If function calls are slow, that is not a problem with the techniques; it is a problem with the language implementation.

      I don't really agree with this. I mean, yes, if slow function calls are a problem then yes it is a language issue that really long term aught to be handled by fixing the implementation. But on the other hand we are engineers and problem solvers that have to work with the tools we have. So assuming that we have good reasons to use Perl, and assuming that functions are a problem then any technique that depends on them heavily is flawed in some situations when using the Perls that are available right now.

      Personally im in the camp that says that for some tasks Perl's method overhead and subroutine overhead becomes unacceptable. That may be because of the type of work I do (reasonably large scale data processing), but thats the way I view it. Now, what I think is really interesting are the techniques that allow you to have your cake and eat it too. So for instance I've found that constructing tailored code that doesnt use subroutine or method calls from a rule set implemented in OO is quite powerful. Each rule knows how to represent itself as a snippet, and once the rules are stiched together you get a single monolithic piece of code that performs very well. At the same time you get a clean conceptual model that you can work with at a higher level of abstraction.

      Anyway, I was hoping that HOP had stuff along this line but your response makes me think not. Nevertheless I still look forward to reading it. :-)

      ---
      $world=~s/war/peace/g

        Said demerphq:
        I mean, yes, if slow function calls are a problem then yes it is a language issue that really long term aught to be handled by fixing the implementation. But on the other hand we are engineers and problem solvers that have to work with the tools we have.

        Sure. But if Perl's function calls are "too slow", where does that leave you with Perl? You can't do functional-style programming, because that would use too many function calls. And you can't do object-oriented style programming, because that would also use too many function calls, and method calls are slower than regular function calls. And you can't write any big or complex programs, because big complex programs are full of functions and then they must be too slow.

        So where does that leave you? I think it leaves you with "Perl is just a scripting language, only good for throwaway scripts, but nothing big or important." Which some people do believe, but I do not.

        Basically, my argument is this: Some language features can be avoided, but functions are not one of those features. Some implementation deficiencies can be worked around, but if function calls are too slow, there is no workaround. Every nontrivial program must contain lots of function calls. So if Perl's function calls are "too slow" (whatever that means, and nobody in this thread has suggested any relevant meaning) then you have only two choices. One is to fix Perl. The other, as you said, is to be a problem-solving engineer, to recognize that you are in a hopeless situation, and to obtain a tool that is not hopelessly defective. I have recently been informed that Java's function calls are faster than Perl's; perhaps that would be a better choice.

        But it seems to me that you cannot reasonably hold the opinion that Perl is worth using for nontrivial programs and also that Perl's function calls are too slow to use.

        I found your description of "constructing tailored code..." etc. above really interesting, but I can't imagine what it looks like, or what you could be doing that the function-call overhead is the bottleneck. I can only imagine that what you are doing does not really make sense, or that it is such a weird special situation that it has little applicability to general discussions like this one. I suppose this is just a failure of my imagination, but I certainly would like to see it.

        Anyway, I was hoping that HOP had stuff along this line...

        Wouldn't it better if it had something in it that you hadn't already thought of?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://488230]
Approved by Tanktalus
Front-paged by Enlil
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2014-08-31 02:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (294 votes), past polls