Planet Smalltalk

May 16, 2012

Cincom Smalltalk - Smalltalk Performance!

Code and application performance is always an interesting topic. For developers, finding and solving performance bottlenecks can be highly productive with the right tools and knowledge, and it can be a very rewarding part of application development.

JR's Smalltalk 4 You - ST 4U 233: Startup Options for VisualWorks

When you start a VisualWorks image, there are a number of startup command line options. Today we'll take a brief look at them

Joachim Tuchel - ESUG 2012: Registration is now open!

Johan Brichau just announced on the ESUG mailing list that you can now register to attend the European Smalltalk Users Groups’ yearly conference ESUG 2012 in Ghent, Belgium: I am pleased to announce that registration for the 20th ESUG Conference … Continue reading

James Robertson - ESUG 2012 Registration Opens

I saw this on the ESUG mailing list:

I am pleased to announce that registration for the 20th ESUG Conference in Ghent, Belgium is now open!
To register, please proceed to the website or go directly to the accomodations page.
Important: do not forget to book your accomodation directly at one of the hotels in Ghent before June30th!

Technorati Tags:

Torsten Bergmann - Cuis Smalltalk mailinglist

There is a new mailinglist to discuss the Cuis Smalltalk system.

May 15, 2012

James Robertson - Spoon weekend 19 May 2012

Craig Latta would like to hear from you about Spoon.

Technorati Tags:

Marten Feldtmann - VASmalltalk – Ubuntu 12.04 LTS, V1

In the next version of this virtual image I added both implementations of VASmalltalk: not only the Linux version is running against a local emsrv – but also a Windows installation, running under Wine under Ubuntu.

I will upload this newer version in the next days.


Filed under: Smalltalk Tagged: LTS 12.04

James Robertson - Give Smalltalk a Try

Cincom Smalltalk - The Mapping Tool’s Database Toolset

Today we’ll have a look at the database toolset from the Mapping Tool

James Savidge - Software Engineer, Cincom, Maidenhead, UK

Cincom is looking for an engineer to work in the ChannelStream project;  details are here.  The location is the Cincom site at Maidenhead just west of London, UK.  Others in the ChannelStream team are on the continent so remote pair-programming and periodic travel may be involved.  ChannelStream has a Seaside-powered web interface.  It manages complex problems of corporate document distribution.

Craig Latta - Spoon weekend 19 May 2012

FYI, this weekend I’ll be preparing some documentation for Spoon, and would be happy to converse in-depth about it here and elsewhere online.


Torsten Bergmann - Try Smalltalk

James Robertson - Memoization for Smalltalk

Travis talks sorting n VisualWorks:

The core default sort algorithm in VisualWorks is hybridization of quicksort and a insertion sort. The implications for this, is that this somewhat expensive toolListDisplayString method may be called repeatedly for some objects. That means redundant CPU cycles. A common solution to this kind of problem is memoization. Memoization basically is a fancy word which means "cache the results of your computation function, so you only evaluate the function once for each unique input and just look up the cached result for subsequent calls."

Technorati Tags:

James Robertson - Smalltalk and Fluentd

There's another logging framework available for Smalltalk, but this one isn't standalone - it's an interface to Fluentd:

Nagare is designed to be simple and scalable. Contrary to other logging frameworks which provide rich set of log output methods (file, socket, DB, etc.), Nagare just connects to fluentd (http://fluentd.org). And Fluentd does the various log processing jobs.

Technorati Tags:

Travis Griggs - Caching and The Way of the Object

Lately, we've had an internal debate about how to make some places where we do sorting go faster. Of course, there's always the caveat: Make it Work, Make it Right, and if you need to, Make it Fast. Learning when you need to care about that last step, is always a sort of art based on experience. Often the answer is simply "all other things considered, it's fast enough, I've got bigger problems to solve elsewhere."

Let's take an example though. Take a collection of Class objects (we'll leave the MetaClasses out), and sort them by their response to toolListDisplayString:

| classes |
classes := Object withAllSubclasses reject: #isMeta.
classes sorted: #toolListDisplayString ascending

In our example, we're using VisualWorks' ability to substitute simple Symbols as replacements for BlockClosures that send a single unary message to their arguments. It is equivalent in behavior to the more traditional:

| classes |
classes := Object withAllSubclasses reject: [:each | each isMeta].
classes sorted: [:each | each toolListDisplayString] ascending

Sending ascending to a BlockClosure before using it was first developed back in this post and this following post. And that was then integrated into VisualWorks 7.8 (or was it 7.8.1?).

The problem with our example, is that the method toolListDisplayString is not cheap. It's more than just concatenating strings for class and namespace names together. It looks at how much context needs to be added to the class name by itself to make it unique. Or put another way, since there are multiple classes in the system with the name Text, it determines it must add some info about the containing namespace, while the class PostgreSQLEXDIBLOBManipulationOutsideTransaction probably only has one instance and doesn't need any namespace info to contextualize it.

The core default sort algorithm in VisualWorks is hybridization of quicksort and a insertion sort. The implications for this, is that this somewhat expensive toolListDisplayString method may be called repeatedly for some objects. That means redundant CPU cycles.

A common solution to this kind of problem is memoization. Memoization basically is a fancy word which means "cache the results of your computation function, so you only evaluate the function once for each unique input and just look up the cached result for subsequent calls."

How to go about doing memoization around sorting sites can be accomplished a number of different ways.


In Place

The first and simplest way is to simply do it right at the sort site. We could rewrite our example to read:

| classes |
memory := IdentityDictionary new.
classes := Core.Object withAllSubclasses reject: [:each | each isMeta].
classes sorted: [:each | memory at: each ifAbsentPut: [each toolListDisplayString]] ascending

This is the simplest thing that could possibly work. That's its single advantage. The disadvantages is that adds a bit code bloat for every place we decide this is worth doing. It intermingles with what was otherwise pretty simple and easy to read. To flip back and forth between memoized and non-memoized is a pain. And it gets done again and again and again at each call site, so there's no real reuse involved. The risk of implementing it wrong is retaken at each implementation.

The desire to be able to easily flip back and forth between memoizing and not, shouldn't be underrated. Memoization is not free. It costs cycles. It is usually trial and error under conditions that the programmer knows to be common for his code, that determine if the overhead of memoizing is less than the cost of the original redundant function.

This technique is best for those that like to write more code. If you like to brag about how much code you've written, how many lines, classes, or methods, this might be for you. It's simple, and you can demonstrate your superior typing speeds.


More Sort Methods

Another approach is to add a new sort method. VisualWorks already has sort, sort:, sorted, sorted:, sortWith:, and probably some I've missed. Application developers tend to add one or two of their own. A common one in the past has been sortBy: which supports using a single arg block. So you figure out how many of these APIs you want to replicate as memoized alternatives and implement them, for example: memoizedSortBy:, etc. This is if you're a good citizen. If you're not so kind, you use something that looks like just another general purpose sorting API (e.g. sorting: aOneArgBlock).

Implementing memoizedSortBy: gives you the advantage of optimizing things a little differently. You can choose to build a parallel vector of objects collect:ing for the function, retaining index information, sort those, and then basically apply those indices to the original input set. Or you can just go with the Dictionary and at:ifAbsent: approach.

Now the only change we need to make to our call site is to change it to:

| classes |
memory := IdentityDictionary new.
classes := Core.Object withAllSubclasses reject: [:each | each isMeta].
classes memoizedSortBy: [:each | each toolListDisplayString]

You'll note that we don't have ascending anymore in there. The SortFunctions stuff is basically incompatible with this approach. Since this API wants to work with single arg blocks, which it's memoizing the results for, it has hard coded the sort direction inside of it.

I consider this the C Programmer's (or procedural) Approach. If at first you don't find a function, try, try, another one. That it is in this simplistic form incompatible with the SortFunctions thing, is personally aggrieving to me (we lose the elegance of setting the direction, as well as chaining functions, or deriving our own rocketship sorts). Another disappointment is that it's one more API I have to figure out which one I should use. I see a family of sort methods, and I've got to figure out (or recall) what the different nuances of each are (this one takes one arg, this one takes none, this one takes two, each has different trade offs, etc).

Finally, it limits the technique of memoization to sorting. What if I want to use memoization for collect:ing over a collection that I know has redundant elements. In that case, I have to go back to the In Place approach.


The Way of the Object

I'd rather take a page from the SortFunction technique. BlockClosures (or more generally, objects which respond to the message value: and fill the roles of functions) are real Objects too. And I'm declaring that they too have a right to be included in the General Love Fest of Polymorphism. The idea here, is that we add a new memoizing method to BlockClosure (and Symbol too so they can continue to stand double as simple BlockClosures). Sending memoizing to a BlockClosure returns a MemoizedFunction object which can do value: just like a BlockClosure. But it keeps a memory of evaluations and uses those when found. My first cut implementation is published as TAG-MemoizedFunctions in the Open Repository.

Now our example just turns in to:

| classes |
classes := Object withAllSubclasses reject: #isMeta.
classes sorted: #toolListDisplayString memoizing ascending

For this simplistic example, slapping memoizing in there is a 10x speed boost.

What do I like about this approach? First of all, it was fun. This kind of thing, to me, is where the zen of Object Oriented dispatch is at (I don't pretend to be brilliant about this at all, Wilf LaLonde probably wrote an article demonstrating this 20 years ago). I like that it is terse. I like that it localizes the decision about whether to memoize around the function itself rather than the API using it. This is the fastest/easiest way to toggle memoization on and off to profile the differences. I like that I can use it with collect:, or detect:, or allSatisfy:, or any method that makes use of first class function objects. And I like that it only took 10 methods and one class to do. Because Less is More.

Happy Memoizing!

(Why does Apple insist on constantly changing "memoizing" to read "memorizing"? Grumble...)

Pharo News - Nagare - a new flexible logger for Smalltalk

Masashi UMEZAWA has developed a new logging library called Nagare.

Nagare is designed to be simple and scalable.

Contrary to other logging frameworks which provide rich set of log
output methods (file, socket, DB, etc.), Nagare just connects to fluentd. And Fluentd does the various log processing jobs.

Features:
- Simple log interfaces with reliable backend
- Semi-structured logging (Not only String, you can store
   structured records in log)
- Flexible - you can easily customise log-tags, log policy, etc.
- Portable (runs on Squeak, Pharo, VisualWorks)

More at http://code.google.com/p/nagare-logger/.


May 14, 2012

The Weekly Squeak - Etoys 5 Released

The latest versionof the software found around the world in the One Laptop Per Child computer — Etoys — is now available from the Squeakland website. In Etoys 5 you’ll find new features such as single-stepping a script, attached watchers, a graph paper tool, and ScratchConnect, a way to connect Etoys and Scratch.


JR's Smalltalk 4 You - ST 4U 232: StartupLoader in Pharo

Mariano Martinex Peck has been improving the StartupLoader in Pharo - it's a way of specifying startup scripts for a Pharo image. Today we'll take a look at it

May 13, 2012

James Robertson - Startup Loader for Pharo

Need to load a bunch of stuff into a new Pharo image before you get to work? Mariano has some tools for that.

Technorati Tags:

Pharo News - StartupLoader: running startUp scripts in Pharo

Blog post by Mariano about StartupLoader:

Hi. Some time ago, I wrote a post about how I build images for my projects. I am downloading new images all the time and because of that I used to have 2 problems: 1) I needed to load several external packages to thestandard Pharo image; 2) I needed to set my own settings and preferences. Today, Pharo 2.0 (which is in development and unstable state) includes most of the packages I always needed to install: shout, code completion, nice browser (Nautilus or OB), refactoring integration, spotlight, etc.  So nowadays I only had problem 1).
In this post, I will show you how I solve that problem using StartupLoader, a nice utility present in Pharo (since Pharo 1.4). IMPORTANT: Everything I mention in this blog is taking into account the “new version” I did of StartupLoader. Before writing this post I have improved it and therefore you need at least a Pharo 2.0 version 20071.

read more...

Independent Misinterpretations - IM 77: History of Smalltalk, Part 2

James and David take the history of Smalltalk from where they left off last time (the mid 90's), and carry it forward to the present.

May 12, 2012

Mariano Martinez Peck - StartupLoader: running startUp scripts in Pharo

Hi. Some time ago, I wrote a post about how I build images for my projects. I am downloading new images all the time and because of that I used to have 2 problems: 1) I needed to load several external packages to the standard Pharo image; 2) I needed to set my own settings and preferences. Today, Pharo 2.0 (which is in development and unstable state) includes most of the packages I always needed to install: shout, code completion, nice browser (Nautilus or OB), refactoring integration, spotlight, etc.  So nowadays I only had problem 1).

In this post, I will show you how I solve that problem using StartupLoader, a nice utility present in Pharo (since Pharo 1.4). IMPORTANT: Everything I mention in this blog is taking into account the “new version” I did of StartupLoader. Before writing this post I have improved it and therefore you need at least a Pharo 2.0 version 20071.

Why we need StartupLoader?

How can we execute something at startup with Pharo? There have traditionally been two known ways (and now in Pharo there is a new third option and it is the reason of this post):

1) Send a .st file as parameter to the VM, that is, you execute the VM like this:

/Users/mariano/Pharo/VM/Pharo.app/Contents/MacOS/Pharo /Users/mariano/Pharo/images/Pharo-1.4.image startup.st

You execute the VM, pass the Pharo image as parameter and then the file. This will be executed during the startup. What’s the problem with this? If I want to always execute the startup in different images I always need to open the image this way, from command line. I just want to open an image with a double-click. Moreover, this file is hand-coded and not versioned in Monticello (what I would like). Besides, there are more limitations as I mention later in this blog.

2) Register your own class in Smalltalk startup list and implement #startUp message to do whatever you want to do. The problem is that my class is not present in the distributed images of Pharo. Therefore I need to manually first load my own code. Same problem: too much work.

New new tool

Remember my problem: I am downloading new images all the time. Having to manually set up my preferences is boring and time-consuming.

The new StartupLoader class searches for and executes .st files from certain locations.  To find these it searches for a ‘.config’ folder in the folder where the image file sits.  Then it looks in the next folder up, then up again and so on until reaching the root folder.  When a ‘.config’ folder is found, StartupLoader looks within this for a ‘pharo’ folder. This contains the startup scripts common to all versions of Pharo, and also optionally a folder per Pharo version holding startup scripts suitable for that version only.  So a typical directory layout might be…

.../some/folders/pharo/Content/Resources/pharo.image.
.../some/folders/pharo/Content/Resources/startup.st
.../some/folders/.config/pharo/author.st
.../some/folders/.config/pharo/useSharedCache.st
.../some/folders/.config/pharo/1.4/mystartupFor14only.st
.../some/folders/.config/pharo/2.0/mystartupFor20only.st

(**Note however that ‘.config’ is an invalid filename on Windows, so ‘..config’ is used instead)

IMPORTANT: I said that StartupLoader will search for a folder ‘.config’ starting from the image directory until the root of the filesystem. What happens if no folder is found? It creates ‘.config’ in the image folder. However, I recommend you create the ‘.config’ following the standard, that is, in the $HOME.

To know the real values for you…
Print the result of “FileDirectory preferencesGeneralFolder” which holds the startup scripts common to all versions of Pharo.
Print the result of “FileDirectory preferencesVersionFolder” which holds the startup scripts specific to the version of the current image.

The order of the search is from the most general to the most specific:

  1. General preferences folder: This is general for all Pharo versions This folder is shared for all the images you open. In my case (in MaxOSX) and Pharo 2.0, it is ’/Users/mariano/.config/pharo/’. In this place, StartupLoader will load ALL existing .st files. This type of startup is useful when we have something to execute for all images of all Pharo versions.
  2. Preference version folder: This is a specific folder for a specific Pharo version. In my case it is  ’/Users/mariano/.config/pharo/2.0/’. This type of startup is useful when we have something to execute for all images of a specific Pharo version.
  3. The image folder: The startup only searches for a file called ‘startup.st’. So if you have such a file in the same directory where the image is, then such script will be executed automatically. This type of startup is usually used to do something that is application-specific or something that only makes sense for the specific image you are using. Now you might ask why we don’t search the image folder for multiple .st files.  This is because it is normal for the image folder to contain .st files not related to started – such as from any file out.  Using one specific file ‘startup.st‘ avoids this while still allowing an image delivered to a client to run a script upon execution on a new system. Be careful if you already were sending your own ‘startup.st’ as parameter to the VM because it will be executed twice ;)

As you can see the order is from the most general to the most specific. Moreover, it does not stop when it finds files in any of them. So all are searched and executed. More specific scripts can even override stuff set in more general ones. It works more or less the same way as variables in UNIX with .bashrc /etc/envirorment, etc…

So you know where the system will search startup files. Now you can directly put your code there and it will be automatically executed during startup. Great!!! So that’s all?  we just write scripts there?  Of course not! ;)

StartupActions

Directly putting code in the files is easy, however, it is not the best choice. For example, what happens if there are certain scripts you want to execute only once on a certain image but some other code that you want to execute each time the image starts? To solve that, among other things, we have the reification of StartupAction. Let’s see how we use them:

| items |
items := OrderedCollection new.
items add: (StartupAction
name: 'Basic settings'
code: [
Author fullName: 'MarianoMartinezPeck'.
Debugger alwaysOpenFullDebugger: true.
]).
StartupLoader default addAtStartupInPreferenceVersionFolder: items named: 'basicSettings.st'.

What we do first is to create an instance of StartupAction using the message #name:code:. We pass as argument a name and the Smalltalk code we want to run inside a block closure. In this example, I just set my username and I put a setting to always open the debugger (no pre-debugger window). So far nothing weird.

The magic comes with the last line, the message #addAtStartupInPreferenceVersionFolder: items named: aFileName  receives a list of startup actions and a filename and stores the actions in a file with the passes argument. So in this case we have only one action called ‘Basic Settings’ and it will be placed in a file called ‘basicSettings.st’. But where? in which of the 3 folders described previously is it placed? well…it depends on the message. In this case, we used the #addAtStartupInPreferenceVersionFolder:named:  (notice the “InPreferenceVersionFolder”). So it put the files in 2). In addition, you can use the messages #addAtStartupInGeneralPreferenceFolder:named: which stores files in 1) and #addAtStartupInImageDirectory: which stores in 3). Notice that with the first two messages we can specify the file name but with the last one we can’t. Remember the last one is always called ‘startup.st’. If you are lazy and don’t want to think the name yourself, you can just use #addAtStartupInPreferenceVersionFolder: which creates a file called ‘startupPharoNN.st’ or #addAtStartupInGeneralPreferenceFolder: that creates a file named ‘startupPharo.st’.

StartupLoader

We saw that when executing the message #addAtStartupInPreferenceVersionFolder: items named:aFilename or any of its variant, a file is created with the code we want to evaluate. Then, when the system starts it will find our file and execute our code. But, how is the resulting file? Exactly as the code we provided? No! Look how our example file ‘/Users/mariano/.config/pharo/2.0/basicSettings.st’ is generated:

StartupLoader default executeAtomicItems: {
StartupAction name: 'Basic settings' code: [Author fullName: 'MarianoMartinezPeck'.
Debugger alwaysOpenFullDebugger: true].
}.

So as you can see, the file is generated by sending a collection of actions to “StartupLoader default executeAtomicItems:”. In this example the collection has only one action, but it would have more if our example has more. So now the StartupLoader will execute all the actions found in the file. Do we execute all actions? No! Actions can be built with a property of “runOnce”. So if an action has already been executed in the current image before the last save, it is not executed again. Executed actions are stored in the singleton instance #default of StartupLoader. Therefore, you have to save the image. If an action generates an error the action is NOT registered as executed. In addition, errors are also stored in the singleton of StartupLoader so you can query them after starting the image by inspecting the result of “StartupLoader default errors”.

Advanced example

As an advanced example, I want to show you the script I am using for my images. For that, I have this Smalltalk code:

setPersonalStartUpPrefernces
"self setPersonalStartUpPrefernces"
| items |
items := OrderedCollection new.

items add: (StartupAction name: 'General Preferences for all Pharo versions' code: [
FileStream stdout lf; nextPutAll: 'Setting general preferences for all Pharo versions'; lf.
Author fullName: 'MarianoMartinezPeck'.
FileStream stdout lf; nextPutAll: 'Finished'; lf.
]).
StartupLoader default addAtStartupInGeneralPreferenceFolder: items named: 'generalSettings.st'.

items add: (StartupAction name: 'Settings' code: [
FileStream stdout lf; nextPutAll: 'Setting general preferences'; lf.
UITheme currentSettings fastDragging: true.
CodeHolder showAnnotationPane: true.
MCCodeTool showAnnotationPane: true.
Deprecation raiseWarning: true.
Debugger alwaysOpenFullDebugger: true.
Parser warningAllowed: false.
FileStream stdout lf; nextPutAll: 'Finished'; lf.
]).
StartupLoader default addAtStartupInPreferenceVersionFolder: items named: 'settings.st'.

items removeAll.
items add: (StartupAction name: 'Nautilus' code: [
FileStream stdout lf; nextPutAll: 'Executing Nautilus related stuff'; lf.
Nautilus pluginClasses add: { NautilusBreadcrumbsPlugin. #top }.
Nautilus pluginClasses add: { AnnotationPanePlugin. #middle }.
FileStream stdout lf; nextPutAll: 'Finished'; lf.
] runOnce: true).
StartupLoader default addAtStartupInPreferenceVersionFolder: items named: 'nautilus.st'.

items removeAll.
items add: (StartupAction name: 'Monticello related stuff' code: [
| sharedPackageCacheDirectory |
FileStream stdout lf; nextPutAll: 'Executing Monticello related stuff'; lf.
sharedPackageCacheDirectory := (FileDirectory on: '/Users/mariano/Pharo/localRepo/')
assureExistence;
yourself.
MCCacheRepository default directory: sharedPackageCacheDirectory.
MCDirectoryRepository defaultDirectoryName: '/Users/mariano/Pharo/localRepo/'.
(MCRepositoryGroup default  repositories
select: [:each | (each isKindOf: MCHttpRepository)
and: [((each locationWithTrailingSlash includesSubString: 'www.squeaksource.com')
or: [each locationWithTrailingSlash includesSubString: 'http://ss3.gemstone.com/ss/'])]
]) do: [:each |
each
user: 'MMP';
password: ((FileDirectory default oldFileNamed: '/Users/mariano/Pharo/repositoriesPassword.txt') contents).
].
FileStream stdout lf; nextPutAll: 'Finished'; lf.
]).
StartupLoader default addAtStartupInPreferenceVersionFolder: items named: 'monticello.st'.

Basically, I have 4 files to customize stuff: 1) general settings;  2) settings for Pharo 2.0; 3) nautilus and 4) monticello related stuff. 1) is for all Pharo versions. So far I am just setting my username. 2) 3) and 4) are for Pharo 2.0 (just because I know they work in Pharo 2.0 and I am not sure if they work in other versions). For nautilus, I don’t want to add the plugins each time (because it would add the plugin several times) so I create a StartupAction using the message #name: nameOfItem code: code runOnce: aBoolean  passing a true to aBoolean.

Using the tool

How to split your stuff in files and actions?

So you may have noticed that: a) #addAtStartupInPreferenceVersionFolder: and friends expect a list of actions; b) you can have multiples files. So, how do you split your code? From what I can see in the framework, there is no restriction. You can have as many actions per files and as many files as you wish. An action has a block of closure that can contain as much code as you want.

I found that one way of splitting your code is when some actions need to be executed only once and some other each time. Another reason may be some code which may be expected to fail for some reason. If it fails, the code after the line that generated the error won’t be executed. Hence, you may want to split that code to a separate action.

How to version and work with this tool?

The way I found to work with this stuff is to have my own class GeneralImageBuilder (put whatever name you want). In such class I have the mentioned method #setPersonalStartUpPrefernces (from the advanced example). So I use Monticello to save and load that project. Then, whenever I want to create the script files and add them to their correct directory, I just evaluate that method.

Be careful with the cache!

In order to support the “runOnce:”, actions are stored in the singleton instance of StartupLoader. After an action is executed (if executed correctly), the action is stored and marked as “executed”. It may happen that later on you modify the scripts by hand, or you change the rules and re-store them or some kind of black magic. So…if you change some of these, I recommend to do 2 things:

  • Remove all existing files from the preference directories (no script is removed automatically). Check methods #remove* in StartupLoader.
  • Remove the existing stored actions in StartupLoader. Check method #cleanSavedActionsAndErrors and #removeAllScriptsAndCleanSavedActions.

Conclusion

I think that the tool is very nice. It is just 3 classes and a very few methods. I have been improving it recently but still, there could be more improvements. Wanna help?  I wanted to summarize this post and write a better class comment, but I am running out of free time. In addition, it would be nice to have some tests ;)

I want to thank to Benjamin Van Ryseghem for doing the first version of the tool and to Ben Coman for fixing the preference folder in Windows and for discussing with me about the performed improvements.

Hope you like it!


Tagged: build, Pharo

May 11, 2012

Norbert Hartl - LRUDictionary: a small least-recently-used style dictionary

For my last project I needed some kind of cache. I had one web service providing the main functionality and that was using another service for session and user information. Having each web request triggering multiple requests internally to resolve user and session data was not an option.

In pharo there is a class called LRUCache. It is like a dictionary where the only implemented method is #at: . The LRUCache is created by providing a size of the dictionary and a factory block. When an element is requested by using at: the factory block will be invoked if the element is not present.

LRUCache does not give you control over the storage of the elements. Either it is there or it will be created and exists then. For my user and session data the situation was slightly more complicated. I don't want to store user information when the user is not confirmed (it can change within the next seconds if the user confirms). And sessions should be removed from the dictionary if they are expired. The removal of expired sessions is not necessary as they would be sorted out automatically. It is an optimization because the cache will be less efficent if expired session block upper position in the LRU order until the reach the tail of the list and get discarded.

To serve my purpose I created a LRUDictionary class. It works like the LRUCache class (yes, I preserved the nice statistics the LRUCache provides about its usage) but adds more of the dictionary protocol to it. I added

at:ifAbsent:
at:ifAbsentPut:
at:ifPresent:
at:put:
removeAt:
removeKey:
removeKey:ifAbsent

The code can be found on squeaksource

Feel free to improve, comment or criticize

James Savidge - Smalltalk Jobs - Cincom - Software Development Manager

With the departure of Alan Knight, the Smalltalk team here at Cincom will need a new manager. Working at Cincom can be quite rewarding, and our Smalltalk tools are among the most important products at the company.

This time around we are looking outside Cincom, and if you have experience with managing a distributed technical team and interacting with a diverse customer base, then you might be a good candidate for the postion.

Yes, balancing the needs of the customers with our geeky need to “get it right”, might seem like herding cats at times, but you will have the opportunity to work with one of the best teams in the industry, and work at a great company. In addition, you would be in a position to help us maintain our leadership in the Smalltalk community, and set the course for the future of Cincom’s Smalltalks.

  • Software Development Manager at Cincom
    • Required Skills:
      • Master’s degree in computer engineering or other appropriate technical discipline
      • 10+ years of progressively responsible software development experience, including at least 2 years of applicable corporate software development leadership experience
      • Hands-on knowledge of technologies, product development methodologies, and programming languages applicable to Cincom Smalltalk development
      • Advanced knowledge of principles, practices, and techniques of product development and project management
      • Proven ability to lead a team of technical staff members to successfully deliver a software product
      • Ability to work effectively with senior management on strategic objectives and long-range plans
      • Demonstrated ability to manage multiple, parallel projects with highly variable scopes
      • Outstanding leadership, communication and presentation skills, verbal and written
      • Exceptional competency in responding to customers in a competent and professional manner
      • Track record of promoting customer-centric solutions and, by setting an example, to instill a spirit of teamwork and cooperation within a large and diverse development organization
    • Wanted Skills:
      • Experience with UML (Unified Modeling Language) and/or Agile/SCRUM methods
    • Additional listings: Cincom
I hope we will be working with one of you soon,
James T. Savidge

View James T. Savidge's profile on LinkedIn


JR's Smalltalk 4 You - ST 4U 231: Code Completion in VA 8.5.1

Instantiations has really improved the code completion support in VA 8.5.1; today we'll look at some of that.

May 09, 2012

James Robertson - DrGeo Android release

Torsten spots some Android progress for Smalltalk:

Hilaire Fernandes made DrGeo for Android available. DrGeo is built using Pharo Smalltalk.

Technorati Tags: , ,

Torsten Bergmann - DrGeo Android release

Hilaire Fernandes made DrGeo for Android available. DrGeo is built using Pharo Smalltalk.


JR's Smalltalk 4 You - ST 4U 230: Using OCX Controls in WindowBuilder

We looked at using OCX controls in the VA Composition Editor; today we'll do the same thing in WB Pro.

Yoshiki Ohshima - [その他] Pharo SmalltalkでAthensを試す

backendはCairoということで、もうだじゃれ入りまくりですが。 0. Mac OS Xのコンピュータを準備。 1. Pharoのイメージをダウンロード。 http://gforge.inria.fr/frs/download.php/30620/Pharo-1.4-14438.zip でok 2. NativeBoost付きVMをダウンロード。今日の時点ではJenkinsにある https://ci.lille.inria.fr/pharo/view/NativeBoost/job/NB-Co ...

May 08, 2012

Squeak Oversight Board - SOB Minutes – 5/7/12

Squeak Oversight Board minutes – 5/07/12

Attending: Colin Putney, Chris Cunnington, Bert Freudenberg, Randal Schwartz

- some ideas were explored for a Squeak event concerning kinds of presentations and intended audience; in addition we discussed who might be a good keynote speaker

- ideas for where we should get a new server were explored, but we’re waiting back to hear from some people, so nothing definitive was decided today

- there is a plan (regardless of the readiness of the new server) to take a week in June and update the squeak.org website to the latest version of Aida

- instead of waiting until next year, some steps will be taken to update the voting procedure. The people who voted this year will automatically be included in a new voting list. The new system will likely be based on the Sugar Labs model with a public list of voters. [1]

- Chris Muller is the new SFC liaison contact at the SOB

[1] http://wiki.sugarlabs.org/go/Sugar_Labs/Members