Apache Arrow is blazingly fast

The code is looking for a min value of an array of doubles of 100M size.
The result is arrow::compute::MinMax is 3-4 times faster than std::minmax_element without noticeable memory overhead.

#include <iostream>
#include <chrono>
#include <vector>
#include <random>
#include <algorithm>
#include <arrow/api.h>
#include <arrow/builder.h>
#include <arrow/compute/api.h>
using namespace std;
std::shared_ptr<std::vector<double>> vector_generate(uint data_size) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> distrib(1.1, 100.9);
std::vector<double> data(data_size);
std::generate_n(data.begin(), data.size(), [&]() { return distrib(gen); });
return std::make_shared<std::vector<double>>(std::move(data));
}
std::shared_ptr<arrow::Array> arrow_from_vector(std::shared_ptr<std::vector<double>> data) {
arrow::DoubleBuilder builder;
auto _ = builder.AppendValues(data->begin(), data->end());
return builder.Finish().ValueOrDie();
}
template<typename Func>
int timed(Func func, std::string func_name) {
auto start = std::chrono::high_resolution_clock::now();
func();
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Execution time (" << func_name << "): " << duration.count() / 1000000.0 << " seconds" << std::endl;
return duration.count();
}
void work(uint data_size) {
std::cout << "---- New experiment (size): " << data_size << std::endl;
const auto vec = vector_generate(data_size);
const auto arr = arrow_from_vector(vec);
auto duration1 = timed([vec](){std::minmax_element(vec->begin(), vec->end());}, "std::min_element");
auto duration2 = timed([arr](){arrow::compute::MinMax(arr).ValueOrDie();}, "arrow::compute::MinMax");
std::cout << "arrow::compute::MinMax is faster: " << (double)duration1 / duration2 << " times" << std::endl;
}
int main()
{
for (uint i = 1000U; i < 1000000000; i*=10)
work(i);
return 0;
}

LeetCode: Divide Two Integers (Solution)

The link to the problem https://leetcode.com/problems/divide-two-integers

public class Solution
{
public int Divide(int dividend, int divisor)
{
var negative = IsResultNegative(dividend, divisor);
var dividendPositive = ToPositive(dividend);
var divisorPositive = ToPositive(divisor);
var resultPositive = DividePositive(dividendPositive, divisorPositive);
return FromPositive(resultPositive, negative);
}
private static uint ToPositive(int input)
{
if (input == int.MinValue)
{
return int.MaxValue + 1u;
}
return (uint)Math.Abs(input);
}
private static int FromPositive(uint input, bool toNegative)
{
var limit = toNegative ? int.MaxValue + 1u : int.MaxValue;
var result = input > limit ? limit : input;
return toNegative ? -(int)result : (int)result;
}
private static uint DividePositive(uint dividend, uint divisor, uint subResult = 0)
{
if (dividend < divisor)
return subResult;
var divisorTemp = divisor;
var newSubResult = 1u;
while (dividend >= divisorTemp << 1 && IsSafeToShiftLeft(divisorTemp))
{
divisorTemp <<= 1;
newSubResult <<= 1;
}
return DividePositive(dividend - divisorTemp, divisor, subResult + newSubResult);
}
private static bool IsSafeToShiftLeft(uint divisorTemp)
{
return divisorTemp < 0x80000000;
}
private static bool IsResultNegative(int dividend, int divisor)
{
return dividend < 0 ^ divisor < 0; // XOR operation
}
}

Breaking Bad: Liskov’s Substitution Principle (LSP) violation

Recently I was watching a very nice explanation of LSP on Christopher Okhravi’s YouTube channel. After approximately five minutes of watching this video I wanted to know one thing: how can I actually break it?

Because, you know, breaking things when you learn gives you better understanding of how they work. Am I right?

Continue reading “Breaking Bad: Liskov’s Substitution Principle (LSP) violation”

Fighting Complexity of a Simple Calculator App

Encouraged by Dmitry aka Senior Software Vlogger recently I read an interesting paper called “Out of the Tar Pit” by Ben Moseley and Peter Marks. Good 50% of the article is way over my head.

According to the paper the two most important ways of how complexity comes to our apps are State and Control. Control is order in which things happen inside app. State is variables that change what and in which order program does. Both of them make an app hard to understand hence to modify.

The less State and Control a computer program has the better. The simplest program “Hello world!” does not have State and has only one thing to do (console output of a hard-coded string).

That’s all right but the authors say that OOP (which I like a lot) does not help fighting complexity. And this conclusion surprised me because… it really does! I wanted to check the authors conclusion by practice.

Continue reading “Fighting Complexity of a Simple Calculator App”