Shrink VirtualBox VDI files with TRIM

Historically I have always tried to keep virtual disks small by defragmenting, clearing unused space and compacting. It works, but it is tedious and takes time. Now there is a much better option, as VirtualBox has TRIM support!

Stop the image if it is running, then open the configuration file with a text editor. Locate the virtual disk and add discard and nonrotational:


<AttachedDevice discard="true" nonrotational="true" type="HardDisk" ... >

The nonrotational setting can be edited in the user interface (Solid-state drive), but my version of VirtualBox still doesn’t expose the discard option.

I’m often using Linux Mint as a guest. Start it and verify that TRIM is available for the disk:


sudo hdparm -I /dev/sda | grep TRIM

Provided that TRIM is in fact supported, add discard support to LVM if it is used. Edit /etc/lvm/lvm.conf and make sure that issue_discards is set:


devices {
    ...
    issue_discards = 1
}

Also edit /etc/fstab and add discard to the file systems, for example:


UUID=somevalue / ext4 discard,errors=remount-ro 0 1

Reboot and delete something big. You should see the vdi file shrink in real time. Is that cool or not? You can also discard unused data manually:


sudo fstrim /

With a file system that has been used for a while that can reduce the size of the vdi file a lot.

Advertisements
Categories: Virtualization

JBoss EAP 6 and CACHE_CONSUMER with Spring DMLC

The documentation for Spring’s DefaultMessageListenerContainer states:

Some Java EE servers only register their JMS resources with an ongoing XA transaction in case of a freshly obtained JMS Connection and Session.

Rumour has it that JBoss EAP is one of the guilty servers, but is it true? We couldn’t find any definitive answers for the recent versions. But yes, caching consumers with JBoss EAP 6 using XA transactions will fail. The application server only enlists with the active transaction when a connection is checked out from the pool. If the consumer is reused for other transactions that will seem to work (no error messages), but in fact the messages are consumed without transactions. If a rollback occurs messages are lost.

In short, be sure to use CACHE_NONE with JBoss EAP 6.

Categories: Java, Performance

Beware of interned strings with G1

Interned strings can always be problematic, as the size of the hash table is fixed. Perhaps the -XX:+UseStringDeduplication option can make things worse, as (according to native memory tracing) it seems to use the same pool. However, at present there is a more pressing problem with Java 8 and 9 using the G1 garbage collector: interned strings may not be garbage collected at all, resulting in a native memory leak. See JDK-8180048. What to do? Stay calm or switch to another garbage collector. But be sure to keep an eye on the native memory usage of your Java applications!

Categories: Java

Fighting with biosboot and efi boot in CentOS 7

In two recent Linux installations I have struggled with biosboot and efi boot partitions. At first I didn’t know why they were needed, I have never seen them before, perhaps because I generally use old hardware for my Linux boxes.

The rule is apparently fairly simple. If the system booted in efi mode, the disks must use gpt and an efi boot partition is required. If on the other hand the system booted in legacy mode there are two options. If the disk is larger than 2T then gpt is required and a biosboot partition is needed. For smaller disks it is possible to use msdos without a biosboot or efi boot partition, using only the mbr for the boot loader.

You can tell if the system booted in efi by checking for /sys/firmware/efi. If it exists the system booted in efi, otherwise it booted in legacy mode. The boot method is controlled by bios settings, not by Linux.

I tried to install CentOS 7. For a simple one-disk installation it is a breeze, but what do you do if you want to use software raid? The installer can create boot and root in raid1, but there is no support for creating efi boot or biosboot partitions on multiple drives.

For biosboot I solved it by escaping to a command prompt, (Ctrl-Alt-F2), creating a gpt disk with gdisk with a single 1M partition created in advance for all disks. That worked, but of course the boot loader is only installed on one of the disks, so after a reboot I had to run grub2-install for all disks.

For efi boot I failed. The installer didn’t like my M2 disk and kept complaining. I tried without it, using two other identical disks. That worked better, but I still couldn’t create the partition from the installer and when I used gdisk the installer would either complain that /boot/efi had to exist on a valid gpt disk or that there was an invalid software raid setup on the newly formatted disks. After several attempts, each needing a reboot cycle, I gave up and booted the system in legacy mode, using msdos disks with classic mbr. Everything worked, including the M2 disk.

This should not be rocket science. The end result is well defined, the problem is when you have to work against the installer rather than with it. I realize that most of Red Hats corporate customers use hardware RAID, but there are many servers out there using software raid as well. Better support for mirrored disks in the installer would be great!

Categories: Linux

Effective low-tech alternative to @formatter:off for Java

I love automatic formatting for source code. Back in 2004 I scrapped the detailed formatting guide for the project I was running and replaced it with a single sentence: all code must be formatted by the automatic formatter using the project’s conventions. Done. Sure, manual formatting can look better, but at what cost (and tedium)?

There are some places where the automatic formatter always fails, though, for example string concatenation for SQL commands. No problem, use @formatter:off and @formatter:on and there you are – until someone comes along who hasn’t enabled the tags. And disabling formatting completely can introduce tabs where there should be spaces, for example.

Fortunately there is an effective low-tech alternative that works everywhere (cross-IDE): comments! Use line comments after each line and the formatter can’t join them:


   "select something from some_table " //
   + " where some_column = ?"

It will still handle indentation.

Categories: Java

Windows 10 update issues

With Windows 10 there is no easy way to block an update. If Windows Update thinks you need it, well then there you are. Perhaps that is good, perhaps it is bad. I don’t like it. However, it turns out to be particularly nasty if an update fails!

In my case the printer driver for HP LaserJet CM1415 had a new version, but the update consistently failed. Not a big deal, the old driver worked well – or so I thought. Unfortunately the failure to install this one update caused Windows Update to ignore all others. It would keep trying with the printer driver every and keep failing. As a result none of the really important updates got through. So, if an update fails, don’t ignore it.

When that had been solved the Anniversary Update started, but consistently failed with a black screen. It took me some time to determine why. Apparently it didn’t play well with TrueCrypt (Windows Home does not support Bitlocker). Decrypting the drive for the update solved the issue.

Categories: Windows

ActiveMQ redelivery plugin fails when client side redelivery is active

We recently had serious issues with the ActiveMQ redelivery plugin. Under high load messages would not be redelivered at all (according to the application logs), they went straight to the DLQ. In isolated tests redelivery worked, but not as intended. We would get six redeliveries in a few milliseconds and then nothing. Why?

It turned out to be a conflict between client-side redelivery and broker redelivery. The client side redelivery kicked in and quickly failed six times. Then when the broker got a chance the maximum redelivery count had already been reached, so the message was moved to the DLQ. See this post.

Following the advice in the post we added jms.redeliveryPolicy.maximumRedeliveries=0 to the broker url, and voila! It worked.

Categories: Java