Search code examples
stringdocker.net-coreredhatstartswith

Performance difference in Docker images


I have a .NET Core 2.0 Console App having different performance results depending on the Docker base image it is running on. The application performs several calls to the String.StartsWith(string) function in .NET. Here is the Program.cs file:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp {
    class Program {

        private static string variable = "MYTEXTSTRING";
        private static IEnumerable<string> collection = new[] { "FAF", "LEP", "GHI" };

        static void Main(string[] args) {

            int counter = args.Length > 0 ? Int32.Parse(args[0]) : 1000;

            var stopwatch = new Stopwatch();
            stopwatch.Start();

            for (int i = 0; i < counter; i++) {
                foreach (string str in collection) {
                    variable.StartsWith(str);
                }
            }

            stopwatch.Stop();

            Console.WriteLine($"Elapsed time: '{stopwatch.ElapsedMilliseconds}ms' - {counter * collection.Count()} calls to string.StartsWith()");

            Console.ReadLine();

        }
    }
}

This code then runs in a Docker container in a Linux Ubuntu VM. Depending on the base image I use, I see very different performance results.

Here is the Docker file using a Red Hat base image:

# Red Hat base image
FROM registry.access.redhat.com/dotnet/dotnet-20-rhel7

# set the working directory
WORKDIR /app

# copy files
ADD . /app

# run Model.Build
CMD ["dotnet", "ConsoleApp.dll", "20000"]

Here is the Docker file using a Linux Debian base image:

# Docker Hub base image
FROM microsoft/dotnet:2.0.5-runtime-jessie

# set the working directory
WORKDIR /app

# copy files
ADD . /app

# run Model.Build
CMD ["dotnet", "ConsoleApp.dll", "20000"]

As you can see, apart from the base image, the two Dockerfiles are actually identical. Here are the performance results I get:

  • Red Hat base image: "Elapsed time: '540ms' - 60000 calls to string.StartsWith()".
  • Docker Hub base image: "Elapsed time: '15ms' - 60000 calls to string.StartsWith()".
  • Native execution: "Elapsed time: '14ms' - 60000 calls to string.StartsWith()"

So, while the container using the Debian base image has performance results very similar to native execution, the container using the Red Hat image is performing a lot slower.

Question: why does the StartWith() function perform so differently? What is causing performance to drop this much when using the Red Hat base image?

Thanks.


Solution

  • StartsWith takes into account the culture. The container cultures differ because they do not have the same LANG environment variable.

    You can use one of the StartsWith overloads to change how the culture is taken into account (e.g. variable.StartsWith(str, StringComparison.Ordinal)).