recursive.codes


The Personal Blog of Todd Sharp

Cloud Cost Cutting: Save Money By Resizing Large Images In Object Storage

Posted By: Todd Sharp on 6/3/2020 12:00 GMT
Tagged: Cloud, Java

Like many of you, I have an account on our Oracle Cloud "always free" tier that I use for hosting personal projects, most notably my personal blog recursive.codes. After importing a large amount of content recently I noticed that I was starting to be billed a few dollars ($2-4) every month. Since I'm an incredibly cheap person I decided to see what I could do to get that cost down. One of the easiest ways to reduce object storage costs is to reduce the number of bytes being stored, so I decided to write a quick script to do just that. 

What?! You don't have an account on the Oracle Cloud "always free" tier yet?  What are you waiting for? You can get 2 Autonomous DB instances, 2 VMs, Object Storage, and much more. For FREE!  

I will explain the script below, but for those who are wondering it is written using the Groovy programming language. Groovy is an optionally typed, dynamic JVM language (that offers static compilation as well) and I've been using it to write both web applications and for simple scripting tasks for the last 9 years. If you've worked with Gradle or Jenkins, you've probably already written some Groovy and you just might not have known it.  If you're a Java user, this script will look familiar to you for the most part. The only tricky bit might be the each closure which is one of the collection method add-ons to the List class in the GDK. If you're looking to learn more about then you should certainly refer to the documentation.

Setup

I usually create a project that is used for common scripts that utilizes a Gradle build file to pull in any necessary dependencies. We can run any Groovy file via Gradle with some simple setup. In this case, my project is for scripts that utilize the OCI Java SDK so I have the following build.gradle in the project root directory.

Then I add a task for each individual script in the project directory so I can run them individually. Here's the task for my ResizeImages.groovy script (that resides in the src/main/groovy/codes/recursive directory):

The Script

The script begins with the creation of an auth provider object and an object storage client instance. It's easiest to use a ConfigFileAuthenticationDetailsProvider, especially if you're already using the OCI CLI locally since you'll have an existing config file to point at.

Confused?  Groovy doesn't require the use of semi-colons. You won't miss them, trust me!

Next, declare a few variables to contain your object storage namespace and the name of the bucket you want to operate on.

In Groovy, def can be used to define a variable without declaring it's type ahead of time. You can even change the type later on by assigning a value of a different type!

Now I create the ListObjectsRequest (indicating that we want the "size" field returned along with each item) and pass the listObjectsRequest to the listObjects method on the client. This gives us back a ListObjectsResponse that we'll iterate over next.

Now we can iterate over the response using the each closure that Groovy adds to java.util.List.

Within the closure, we receive the current list item, in this case, an ObjectSummary containing information about the object. If the object is larger than 500kb then we'll construct a GetObjectRequest to retrieve the object, then resize the image by 50%, save a copy locally in case something happens, then craft and send a PutObjectRequest to overwrite the previous image. Certainly, I could have added more logic to make sure the object was a valid image first, but in this case, I know for a fact that all of the items in my bucket were either JPG or PNG. Here's the fully populated loop.

So what did this do for me? Pictures and graphs often tell a better story than words, so let's look at my bucket metrics for the past 7 days:

As you can see, the total bucket size was reduced from around 205MB to around 71MB. This will easily result in approximately 65% cost savings for me every month. Which means I've got about an extra dollar or two to spend every month. Yeah!!!

Check out the entire script on GitHub!

Photo by Geronimo Giqueaux on Unsplash



Related Posts

Building Cross Platform Native Images With GraalVM

Building Cross Platform Native Images With GraalVM

A few weeks ago, I blogged about a utility that I created that helps you debug your serverless functions in the Oracle Cloud. The code behind that project...

Cloud Cost Cutting: Autoscaling Your Dev/QA Environments

Cloud Cost Cutting: Autoscaling Your Dev/QA Environments

I've worked on many software projects over the last 16 years, and one thing that each of those projects had in common was the existence of an environment...

Simple Serverless Logging For Oracle Functions

Simple Serverless Logging For Oracle Functions

Working with serverless functions represents a new way of thinking for many developers. Dealing with stateless functions, for example, can be a challenge...

Note: Comments are currently closed on this blog. Disqus is simply too bloated to justify its use with the low volume of comments on this blog. Please visit my contact page if you have something to say!