public void GlobalSetup()
        {
            try
            {
                var eventsApi = new ApiFacade
                {
                    ProgressHandler = new ConsoleProgress()
                };

                var filePath = Environment.GetEnvironmentVariable(FilePathEnvVariable);
                BucketContainer = eventsApi.LoadEventsFromFileAsync(filePath, LoadStrategyType.LoadEventsAndPayloadsForChart)
                                  .GetAwaiter()
                                  .GetResult();

                var lastBucket = BucketContainer.GetLastBucket();
                Start = BucketContainer.FirstTimestamp;
                End   = lastBucket?.GetAbsoluteTimeForEvent(lastBucket.GetLastEvent()) ?? 0;
            }
            catch (Exception exc)
            {
                Console.WriteLine();
                Console.WriteLine(exc.ToString());
            }
        }
        /// <summary>
        /// Gets densities for segments with size equal to <paramref name="segmentSize"/>
        /// </summary>
        /// <param name="container">Bucket container</param>
        /// <param name="start">Start time</param>
        /// <param name="end">End time</param>
        /// <param name="segmentSize">Length/duration of one segment</param>
        /// <param name="targetBuffer">Targer buffer into  which calculated densities are saved</param>
        /// <returns></returns>
        public static Span <double> GetDensities(BucketContainer container, long start, long end, long segmentSize, ref double[] targetBuffer)
        {
            if (end <= start)
            {
                throw new ArgumentException("Wrong interval. End timestamp must be greater than start timestamp.");
            }

            if (end - start < segmentSize)
            {
                throw new ArgumentException("Segment size is too big for this time interval", nameof(segmentSize));
            }


            var lastBucket = container.GetLastBucket();
            var maxTime    = lastBucket.GetAbsoluteTimeForEvent(lastBucket.GetLastEvent());

            if (end > maxTime + 1)
            {
                end = maxTime + 1;
            }

            // Start time is out of range
            if (end < start)
            {
                return(Span <double> .Empty);
            }

            ushort totalSegments = GetTotalSegments(start, end, segmentSize);

            if (targetBuffer == null)
            {
                targetBuffer = new double[totalSegments];
            }
            else if (targetBuffer.Length < totalSegments)
            {
                throw new ArgumentException("Target buffer is too short", nameof(targetBuffer));
            }

            int processedSegmentsUsingHints = -1;

            try
            {
                checked
                {
                    container.DensityHintContainer?.TrySetDensitiesUsingHints(
                        start - container.FirstTimestamp,
                        end - container.FirstTimestamp,
                        segmentSize,
                        targetBuffer,
                        out processedSegmentsUsingHints
                        );
                }
            }
            catch (OverflowException)
            {
                throw new InvalidOperationException("Too big range of events");
            }

#if DEBUG
            if (processedSegmentsUsingHints == 0 && segmentSize >= 10_000_000)
            {
                Debug.Fail("Density calculation is perfoming in unoptimized way. It can be eliminated by adjusting range and segment size to appropriate values.");
            }
#endif

            if (processedSegmentsUsingHints < 0)
            {
                processedSegmentsUsingHints = 0;
            }

            if (processedSegmentsUsingHints == totalSegments)
            {
                return(targetBuffer.AsSpan(0, totalSegments));
            }

            start += processedSegmentsUsingHints * segmentSize;
            int uncalculatedDensitiesCount = totalSegments - processedSegmentsUsingHints;

            var targetBufferCopy = targetBuffer;
            Parallel.ForEach(GetPartitions(start, segmentSize, targetBuffer.AsSpan(processedSegmentsUsingHints, uncalculatedDensitiesCount)), (partition) =>
            {
                Span <double> batch = targetBufferCopy.AsSpan(processedSegmentsUsingHints, uncalculatedDensitiesCount)
                                      .Slice(partition.leftBoundary, partition.batchLength);

                DensityCalculator.CalculateDensities(
                    container.Buckets,
                    new DensityCalculationRequest(partition.start, partition.end, segmentSize),
                    batch,
                    true,
                    out long processedRange
                    );
            });


            return(targetBuffer.AsSpan(0, totalSegments));
        }