---
title: "LinkedIn Benchmarks again"
description: "Another day, another dollar. LinkedIn has the tips for you! Performance, performance! Let's get right into it."
updated: 2025-09-15
tags: ["C#", ".NET", "Performance", "LinkedIn"]
canonical: "https://steven-giesel.com/blogPost/06cb9eb9-927e-4bc6-a68a-1471288b9609/linkedin-benchmarks-again"
---

# LinkedIn Benchmarks again

Another day, another dollar. LinkedIn has the tips for you! Performance, performance! Let's get right into it.

## Slicing a list

The benchmarks shows roughly something like this:
```csharp

[MemoryDiagnoser]
public class ListBenchmarks
{
    private static readonly List<string> _userIds = Enumerable.Range(1, 1000).Select(i => $"user{i}").ToList();
    
    [Benchmark(Baseline = true)]
    public List<string> SkipAndTake()
    {
        return _userIds.Skip(200).Take(200).ToList();
    }
    
    // Range operator (C# 8.0+)
    [Benchmark]
    public List<string> Take()
    {
        return _userIds[200..400].ToList();
    }

    [Benchmark]
    public List<string> GetRange()
    {
        return _userIds.GetRange(200, 200);
    }
}
```

So we are slicing a list with different mechanism and compare the differences. If I run that on my machine, I get something like this:

```csharp
| Method      | Mean      | Error    | StdDev   | Ratio | RatioSD | Gen0   | Gen1   | Allocated | Alloc Ratio |
|------------ |----------:|---------:|---------:|------:|--------:|-------:|-------:|----------:|------------:|
| SkipAndTake |  99.95 ns | 2.001 ns | 1.774 ns |  1.00 |    0.02 | 0.2093 | 0.0006 |   1.71 KB |        1.00 |
| Take        | 169.00 ns | 3.373 ns | 6.335 ns |  1.69 |    0.07 | 0.3958 | 0.0036 |   3.23 KB |        1.89 |
| GetRange    |  83.59 ns | 1.688 ns | 2.820 ns |  0.84 |    0.03 | 0.1979 | 0.0012 |   1.62 KB |        0.95 |
```

So `GetRange` is by far the fastest with the least amount of allocations. Now let's ignore for a minute that the sample set isn't that high. The original post doesn't provide the full setup so I had to second-guess. 

## The issue

What is odd is the big difference in runtime and allocation for `Take` (that uses the `Range` object and operation introduced in C# 8). How can this take "so long"? Well the answer is, because the code is wrong: Using `[start..end]` on a List, is basically calling the [`Slice`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.slice?view=net-9.0#system-collections-generic-list-1-slice(system-int32-system-int32)) method. You can also play around on [sharplab.io](https://sharplab.io/#v2:CYLg1APgAgDABFAjAFgNwFgBQsGIHQAyAlgHYCOGmWUAzAgExzEDOALgEICmJAxgBYBbAIYAnANbMsAbyxw5cAA4iiANyGtOuAGxwRnIcAD2JADYBPJkTYAeJDAB8cAPoBXZpxEBJYMzgBeOABREhcBDyEAIxNOPAAlIRIAc04ACkQAGjhEGByYAEo8AGVOaJ5WFKJ/RwASACI3DykiAF9agoAVQxZyvMp5OFl5WksbO0dCsSIFAEESYHahMVS8wbkZTH7+qAB2ZwavHyLJhRT6HI7F1LP8vE7ulN7VuGanp+Hu22zHBaWHp/XNkNdq53AdmABta54PDIHIAXVuXSsPT68heVA2QzoHzGcAA4pxWPEkst/k8tsD9t5mHgCUSEslTjlMtdHpi5OjmkA==) with that code.

`Slice` is defined as: `public System.Collections.Generic.List<T> Slice(int start, int length);` The compiler helps you out to transform your `Range` object into `start` and `length`. 

> Creates a shallow copy [...]

So you get back a `List` which holds that slice already. There is no reason to call `ToList` again! Now, you could argue: "Hey Steven, but this is a shallow copy and therefore if you change index 212, the new slice would see that change as well. `Skip(...).Take(...)` would behave differently here!" Well - you are technically correct, but the last one in the set, is: [`GetRange` ](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.getrange?view=net-9.0) and you can guess what this method does:

> Creates a shallow copy of a range of elements in the source List<T>.
	
Soooooooo. The benchmark does not compare the same aspect across the board. Either `GetRange` also gets a `ToList` slapped on top, or we are checking way different things here!
	
As always: Check the code in depth - understand what folks are posting online. Often times, it makes a nice show but doesn't hold true if you uncover one layer below.