Django: use global variables on rendering templates

Problem

Some settings or global value is used in every template or, for example, in base layout template. This value should be passed as context variable to each template. I call such value a global context variable in this post.

For instance, it can be a Google Analytics Code, which should be used in production, but not in staging or development environments. In this case, it’s fine to move GA code to the settings file (of course, if different settings used for different environments). Though need to find a way to get the value from the settings and pass it to the template context before rendering.

Solutions

There are a few simple solutions that solve the described problem:
  1. Add global variable to the template context in every view. But according to DRY and good sense this is a bad solution.
  2. Write a tag to fetch setting value by name and output it. Nice solution and flexible enough in case we need to show different settings in different pages. The only disadvantage is fetching setting value each time it’s accessed. But in most cases this is a minor.
  3. Write a context processor. In the documentation said that context processor is a method that takes a request object as argument and returns a dictionary of items to be merged into the context. In other words, context processor returns a dictionary of items that will be available in template on render phase. In our case, we can get setting value and return from our own context processor method.

    from django.conf import settings
    
    def global_vars(request):
        return {'GA_CODE': settings.GA_CODE}
    
    Also, need to declare our context processor in settings.TEMPLATE_CONTEXT_PROCESSORS:

    TEMPLATE_CONTEXT_PROCESSORS = (
       . . . 
       'synctab.website.context_processors.global_vars',
    )
    
    From now, GA_CODE context variable can be used in any template, and will be processed correctly.

In my opinion, the best decision for fixed list of globally accessed template context variables is a custom context provider. It's also a right way, if most or all templates use same global variables. Otherwise, it's good to write a few tags to cover access to the global state, like settings.

tmpfs: work with your data even faster

Currently improving IDEA performance by copying cache files into the RAM using tmpfs. Actually, tmpfs and ramfs are good ideas.

As described in Wikipedia: tmpfs is intended to appear as a mounted file system, but stored in volatile memory instead of a persistent storage device. Simply put, when you copy a file to such FS, this means that you copy a file to the RAM. When you create a file in this FS, this means you create a file in RAM. When you delete a file in this FS, this means you delete a file in a RAM. And so on.

The negative side of tmpfs is that it's not backed by any storage: on restart or system crash you'll lost your files and data stored in tmpfs. But on system start you can either copy files from the disk to the memory again and continue to work.

In case of IDEA cache, I will need to write a simple script that periodically copies the cache from tmpfs to the disk. So, on restart, I can simply restore cache, and don't need to wait while re-caching is done.

So, how to create a tmpfs storage? It's pretty easy to do with next commands. Here I create an empty directory tmp and mount it as tmpfs filesystem.
# mkdir ~/tmp
# mount -t tmpfs -o size=500m tmpfs ~/tmp
Option size=500m limits memory usage to 500m. tmpfs also supports flushing content to the swap when need. This is one of the main differences between tmpfs and ramfs. ramfs is not limited and can grow dynamically, and the used memory can't be freed or flush to swap. The negative side of such dynamic nature of ramfs is that system can hung when no free memory left.

To read from and write content to RAM is much much faster than to do the same operations with a file on disk. It's pretty good optimization if you need to support read-only content or content that can easily be restored when need.

Such type of content is a hosted website. You can decrease page or resource loading time by moving them from hard disk to the memory filesystem.
 # mkdir /var/www/www.example.com
 # mount -t tmpfs -o size=50M tmpfs /var/www/www.example.com
 # cp -R /home/www/www.example.com/* /var/www/www.example/com

To mount tmpfs automatically on system load, you will need to add another record to yours /etc/fstab configuration file. The only you need to do now is execute next command on system start:
 # cp -R /home/www/www.example.com/* /var/www/www.example/com

As a summary, tmpfs is a good way to work with large amount of files or data that need to be accessed or processed quickly. Such data also is either read-only or can be easily recreated. Samples of such data are static websites, website resources, temporary cache etc. When need to process large amount of data, you can also split it into small pieces and process each one by one. tmpfs is also takes a limited amount of RAM, and can increase over that amount.

Performance Optimization for Android

Here is the list of the performance optimization tips when developing Android applications:

  • Avoid creating objects if you don’t need them.
  • Avoid memory allocation if you can work without it.
  • Array of ints is preferred than array of Integers.
  • Two parallel arrays of ints are a lot more efficient than an array of (int,int) objects. Two parallel arrays of Foo and Bar are a lot more efficient than an array of (Foo,Bar) objects.
  • Avoid creating short-term temporary objects if you can.
  • Make your method static. Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state.
  • It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.
  • Direct field access is about 7x faster than invoking a trivial getter.
  • Use static final for constants.
  • Prefer for-each loop.
  • Declare fields and methods accessed by inner classes to have package access, rather than private access.

Read Designing for Performance article from Android Dev Guide to find more details and samples.

List also available as gist.

Rename of GitHub account and Deploy Keys

Today I've fixed failed builds that were caused by renaming GitHub account. Bamboo couldn't pull the changes from GitHub master repository after rename.

So, I corrected the account name in the .git/config file for origin remote. But this didn't help - I had same the same problem to pull the changes.

That was a security problem: GitHub denied access to the repository, because I don't have access to the old repository (of course, that because account name was changed).

After some investigation, I decided to drop existing Deploy Key and create the same again.
And VoilĂ ! This small manipulation fixed the problem with access to the GitHub repository and now builds are green again.