Quickly test SQL Server using Docker

SQL Server is a large application. The installation copies lots of files and creates new services. If you want to test a version of SQL Server, you may not want to install it on your computer. Instead of creating a virtual machine, you can get a ready to run image from docker. This is much easier to install and, as a VM, it won't pollute your computer. Indeed, you can remove everything with just one command.

  1. Install feature Container

Install Containers feature

  1. Download and install docker tools
  2. Switch to Windows container

Switch to Windows containers

  1. Get the image you want: mssql-server-windows or mssql-server-windows-express
docker pull microsoft/mssql-server-windows
docker pull microsoft/mssql-server-windows-express
  1. Run the container
docker run -e ACCEPT_EULA=Y -e "SA_PASSWORD=RUc@ysd@f_P*yq4é" -p 1433:1433 --name sqlserver -d microsoft/mssql-server-windows

Note 1: If you already run a SQL Server on you computer, you may need to change the port exposed by the container: replace 1433:1433 by <anotherport>:1433

Note 2: you must use a complex password or you won't be able to connect using the sa account

  1. Check the container is started
docker ps -a

Docker ps result

  1. Connect using SQL Server Management Studio

First, you must download SSMS Then, you must get the IP address of the container:

docker inspect sqlserver | find "IPAddress"":"

container IP address

Finally, you can connect using the IP address and the sa account.

SSMS

Note: if you get an authentication error, you must recreate the container with a stronger password

  1. Delete the container

When you want to delete the container, you have to run the following command:

docker stop sqlserver
docker rm sqlserver

If you want to recreate a new container, go to the step 5. It will take just a few seconds to start 😃

Compiling TypeScript using Gulp in Visual Studio

Nowadays, most of us are using TypeScript as a replacement of JavaScript. If you are not, maybe you should look at this previous post: Still not using TypeScript?. TypeScript files must be compiled before you can use them in the browser. Visual Studio does it automatically very great. However, if you want to have a more advanced build workflow, for instance to minify files or running tests, you may want to use a tool like grunt, gulp or webpack. In this post, I'll use Gulp, a toolkit that helps you automate painful or time-consuming tasks in your development workflow.

Gulp logo

In this post, we'll see how Gulp can replace the automatic compilation of TypeScript file provided by Visual Studio.

Disabling automatic TypeScript compilation

First, you need to disable the automatic compilation of TypeScript files in Visual Studio. Open the csproj file and add the TypeScriptCompileBlocked element:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
  </PropertyGroup>

  ...

</Project>

Adding the Gulpfile

Then, you need to install gulp using npm. This will allow to execute gulp from the command line. If you haven't already installed npm, you can get it there.

npm install -g gulp

Then, create the package.json. This file contains information about your project and the list of packages needed to build your project. To create a new package.json file, use npm init and follow the steps (if you don't want to read, press enter until the end):

npm init

Then, you need to install the packages required to compiled TypeScript using gulp:

  • TypeScript the TypeScript compiler
  • gulp-typescript a gulp plugin for handling TypeScript compilation workflow
  • gulp-sourcemaps a gulp plugin for generating source maps, so you can easily debug your TypeScript code in the browser
npm install --save-dev gulp
npm install --save-dev gulp-sourcemaps
npm install --save-dev typescript
npm install --save-dev gulp-typescript

Your package.json should looks like:

{
  "name": "sample",
  "version": "1.0.0",
  "description": "",
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-sourcemaps": "^2.6.1",
    "gulp-typescript": "^3.2.2",
    "typescript": "^2.5.3"
  }
}

Now, you can create the gulpfile. Let's add a new file gulpfile.js at the root of the project.

"use strict";

var gulp = require("gulp");

gulp.task("default", ["js"]);

var tsProject;
gulp.task("js", function () {
    var ts = require("gulp-typescript");
    var sourcemaps = require('gulp-sourcemaps');

    if (!tsProject) {
        tsProject = ts.createProject("tsconfig.json");
    }

    var reporter = ts.reporter.fullReporter();
    var tsResult = tsProject.src()
        .pipe(sourcemaps.init())
        .pipe(tsProject(reporter));

    return tsResult.js
        .pipe(sourcemaps.write())
        .pipe(gulp.dest("wwwroot/js"));
});

If you run the gulp command, your TypeScript file will be compiled. This is ok, but we do want the file to be compiled as soon as they are modified. Let's add the watch command. This command will run the js command each time a ts file under wwwroot/js/ is modified.

gulp.task("watch", ["watch-js"]); // Maybe you'll add a watch-css or something else

gulp.task("watch-js", /* run the "js" task at the beginning */ ["js"], function () {
    return gulp.watch(["./wwwroot/js/**/*.ts"], ["js"]); // run the "js" task when a file is modified
});

You can now use the following command to compile your TypeScript files:

gulp watch

The hardest part is done. Now, you want to use gulp from Visual Studio. I mean, I don't want to start a console and run the command each time I open the project. Instead, I want it to be automatically started, and I want to see any error in Visual Studio.

Running gulp when the solution is opened

Open the task runner:

It lists the available tasks in the gulp file:

You can double-click to execute a task.

To launch the watch task when you open the solution. The task runner has a notion of bindings. It allows you to run a task on certain events in Visual Studio.

Add task runner binding

Conclusion

The default integration of TypeScript in Visual Studio is very good. However, if you prefer using a task runner such as Gulp, you can also easily integrate it into Visual Studio. This allows you to handle more advanced scenario, such as bundle and minify JavaScript and CSS files.

Comparing implementations with BenchmarkDotnet

Sometimes you want to improve the performance of a function. So, you need to compare the performance of one or many different implementations to find the most performant in term of time or/and memory. You can create a console application and use a Stopwatch to measure the time of each variant of your function. But then, how can you easily compare how your function behave in x64 and x86, or on different runtimes. Are the execution of code well isolated? And why an implementation is better than the other?

To help you in this task, you can use BenchmarkDotNet, a powerful .NET library for benchmarking.

Logo BenchmarkDotNet

Let's test BenchmarkDotNet with a simple function that convert an byte array to an hexadecimal string. We'll use 4 implementations coming from StackOverflow:

  1. The basic implementation, often found on StackOverflow
public string ToHexWithStringBuilder(byte[] bytes)
{
    var hex = new StringBuilder(bytes.Length * 2);
    foreach (byte b in bytes)
        hex.Append(b.ToString("X2"));
    return hex.ToString();
}
  1. Another implementation using BitConverter, a little bit shorter
public string ToHexWithBitConverter(byte[] bytes)
{
    var hex = BitConverter.ToString(bytes);
    return hex.Replace("-", "");
}
  1. Another implementation with bit operations
public string ToHexWithLookupAndShift(byte[] bytes)
{
    const string hexAlphabet = "0123456789ABCDEF";
    var result = new StringBuilder(bytes.Length * 2);
    foreach (byte b in bytes)
    {
        result.Append(hexAlphabet[b >> 4]);
        result.Append(hexAlphabet[b & 0xF]);
    }
    return result.ToString();
}
  1. The last one is more tricky, but it works 😃
public string ToHexWithByteManipulation(byte[] bytes)
{
    var c = new char[bytes.Length * 2];
    int b;
    for (int i = 0; i < bytes.Length; i++)
    {
        b = bytes[i] >> 4;
        c[i * 2] = (char)(55 + b + (((b - 10) >> 31) & -7));
        b = bytes[i] & 0xF;
        c[i * 2 + 1] = (char)(55 + b + (((b - 10) >> 31) & -7));
    }
    return new string(c);
}

Using BenchmarkDotNet to compare the 4 implementations

First, create a console application. Add the following NuGet packages: - BenchmarkDotNet - BenchmarkDotNet.Diagnostics.Windows: provides additional data about runs

Then, create a class that contains the code to test, one method per implementation. Each method must be decorated by the [Benchmark] attribute. We want to test the implementation with different array sizes. BenchmarkDotNet provides a way to set parameters in the [Params] attribute. Let's see how it looks:

[OrderProvider(SummaryOrderPolicy.FastestToSlowest)] // Order the result
[RyuJitX64Job, LegacyJitX86Job] // Run with x64 and x86 runtimes
[MemoryDiagnoser] // Analyse the memory usage
public class ByteArrayToHexaBenchmark
{
    // Initialize the byte array for each run
    private byte[] _array;

    [Params(10, 1000, 10000)]
    public int Size { get; set; }

    [GlobalSetup]
    public void Setup()
    {
        _array = Enumerable.Range(0, Size).Select(i => (byte)i).ToArray();
    }

    // Code to benchmark
    [Benchmark]
    public string ToHexWithStringBuilder() => ToHexWithStringBuilder(_array);

    [Benchmark]
    public string ToHexWithBitConverter() => ToHexWithBitConverter(_array);

    [Benchmark]
    public string ToHexWithLookupAndShift() => ToHexWithLookupAndShift(_array);

    [Benchmark]
    public string ToHexWithByteManipulation() => ToHexWithByteManipulation(_array);

    // Actual implementations
    // code omitted for brevity... copy from above
}

Then, you run the benchmark:

public class Program
{
    public static void Main()
    {
        BenchmarkRunner.Run<ByteArrayToHexaBenchmark>();
    }
}

Now, you can run the application in release configuration to get the result:

Result

It's very easy to find the best implementation 😃

If you want to understand why a method behave differently, you can use diagnosers. In the previous example, we use the [MemoryDiagnoser] attribute to get the memory used by each run. You can also use the [InliningDiagnoser] to determine if methods are inlined by the JIT. You can also get more advanced data using [HardwareCounters]. For instance, you can get the number of branch mispredictions. This gives you great insights on the behavior of your functions.

Conclusion

BenchmarkDotNet is very easy to set up, and gives you very accurate results in a few seconds. Thanks to the diagnosers, you can clearly understand how a function behave at runtime, and take some actions to improve it. BenchmarkDotNet must be part of your toolbox.

Windows Console (cmd) Tips

As a developper or an administrator, you often use the Windows Console. Before Windows 10 and Windows Server 2016, it was a pain. The main burden was the 80 columns limitation. But Microsoft has finally decided to make some improvements. The major improvement is the console now support more than 80 columns and common shortcuts such as Ctrl+C and Ctrl+V. Here's are some tips to help you using the console.

Quickly open a cmd from the explorer

You often want to open a console in a specific directory. Instead of using the cd command, you can open it from the explorer. Simply enter cmd in the search bar and press enter. You can focus the search bar by pressing CTRL+L.

Open Windows Console

Of course, you can replace cmd by powershell 😉

Change the transparency (Ctrl+Shift+Mouse wheel)

You can change the transparency of the console using Ctrl+Shift+Mouse wheel or Ctrl+Shift++ and Ctrl+Shift+-. This allows to view the window behind.

Full Screen (F11)

If you are only using the console, such as on Windows Server Core, you can show the console in full screen using F11 or Alt+Enter. This will make your Windows looks like Linux 😃

Windows Console fullscreen

Commands history (F7)

It's nice to avoid typing a command twice. The console keeps an history of all the executed commands, so you can reuse them latter. Navigating using up and down is not so useful as you don't always know which is the previous command. The console has an awesome ui for showing previous commands 😃 You can show it using F7

Windows Console history

Find text (Ctrl+F)

Sometimes you need to search in the output of a command. Of course you can read the whole output and find what you are looking for. But, if the output is very long, you'll spend long minutes. As in many applications, you can find text using Ctrl+F

Windows Console find

TypeScript - External Helpers Library

TypeScript allows you to use ES next features while targeting ES5. The compiler will rewrite the code to be compatible with the targeted version. To rewrite some functionnalities, the compiler emits helper functions. There are currently 15 functions:

  • __extends for inheritance
  • __awaiter and __generator for async/await
  • __assign, __spread and __rest for object spread and rest
  • __decorate, __param and __metadata for decorators

These functions are added automatically at the beginning of each files when needed. For instance, if you use await in a ts file, the compiler will emit the following functions:

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [0, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};

You can add up to 150 lines of code in every js files depending on the features you use. If you have less then 10 files, maybe you don't care. But if you are working on a large projects with hundreds of files, you may want to declare the helper function only once. Keep in mind that reducing the size of the js files will reduce the time required to download them for the clients.

noEmitHelpers flag

TypeScript 2.1 introduced a new flag to prevent the compiler from generating the helpers. This means this is your responsability to add the helpers. The generated code will use them as if it was emitted by the compiler.

You can download the helpers using npm:

npm install tslib

Then, add the tslib.js in you html page:

<html>
    <head>
        <script src="node_modules/tslib/tslib.js"></script>
        <script src="file.js"></script>
    </head>
    <body>
    </body>
</html>

Then, you must configure the TypeScript compiler to not emit the helpers:

{
    "compilerOptions": {
        "noEmitHelpers": true
    }
}

importHelpers flags

If you are using modules, you can instruct the compiler to import tslib as a module:

{
    "compilerOptions": {
        "importHelpers": true,
        "module": "commonjs"
    }
}

This will generate the following code at the beginning of the js file:

var tslib_1 = require("tslib");

Conclusion

If you are working on a medium or large project, you should take a few minutes to configure the noEmitHelpers or importHelpers options. This will reduce the size of the js files and so, improve the loading time of your pages.