Архив метки: извращения

Сага о скорости sscanf

В нашем проекте есть одно из мест при чтении, когда надо распарсить строчку с числами вида «{ 123, 234, 345, 456, 567 }». Там всегда стоял сишный код декодирования через scanf. Ну а потом там пришлось все переделывать, и я на автомате написал декодирование в Qt стиле. А потом решил проверить что же будет быстрее.

Итого, у нас 2 варианта:
1) Ищем каждую первую цифру из каждого из чисел, после чего натравливаем scanf()
2) Сплитим строчку по разделителю, после чего для каждой полученной строки исполняем QString().toInt()

Для проверки что же работает быстрее я написал следующий код:

#include <QCoreApplication>
#include <QtGlobal>

#include <QElapsedTimer>
#include <QString>
#include <QStringList>
#include <QDebug>

#include <stdio.h>

int main(int argc, char *argv[])
{
    QByteArray r;
    for (int i = 0; i < 1000000; i++) {
        float a;
        int b = rand();
        a = *reinterpret_cast<float*>(&b);
        r += QString::number(rand()).toUtf8() + '\0';
    }

    //------------------------------------------
    //------------------------------------------

    QElapsedTimer timer;
    timer.start();

    QList<QByteArray> l = r.split('\0');
    float res = 0;
    for (int i = 0; i < l.size(); i++) {
        res += l.at(i).toFloat();
    }

    qDebug() << res << timer.elapsed();

    //------------------------------------------

    timer.start();

    const char *data = r.data();
    int size = r.size() - 1;
    res = 0;
    float f;
    for (int i = 0; i < size; i++)
        if (data[i] == '\0') {
            sscanf(data + i + 1, "%f", &f);
            res += f;
        }

    qDebug() << res << timer.elapsed();

    return 0;
}

Дебаг сборка
Qt: 165мс на декодирование
Си: 171мс на декодирование

Релиз сборка
Qt: 144мс
Си: 153мс

Массив чисел можно генерить как из целых, так и из float — скорость от этого особо не изменится. Зато скорость знатно меняется, если в качестве разделителя использовать не \0, а, допустим, просто пробел.

В таком случае, если уменьшить количество чисел с 1000000 до 100000, скорости будут такими (релиз):
Qt: 18мс
Си: 963мс

Знаете что это значит? Это значит, что если втупую написать код на Си, ожидая что он будет работать быстрее, то он не только может оказаться медленнее, он может совершенно случайно начать работать за квадрат вместо линии, которую обеспечивает Qt. Остается только догадываться насколько эффективно можно использовать еще более быстрый инструмент — ассемблер.

Ни дня без коммитов

Мой github

Прожил 73 дня, ежедневно модифицируя BSA-Analytics. Первые пару недель непрерывность была случайной, потом она стала искусственной. По внутренним правилам нельзя было переводить часы, заводить фиктивные задачи и отправлять коммиты с пробелами. Стрик был прерван случайно, я в тот день физически возился с сервером и просто забыл про отсутствие коммитов.

Положительные эффекты:

  • Проект не выгружается из памяти, в любой момент я все помню и могу что-нибудь реализовать
  • Абсолютно все мелочи, типа умения программы выдавать свою версию, реализуются, потому что надо что-то писать. Что-то простое, но не особо нужное, зачастую написать проще, чем что-то сложное. А программа состоит из мелочей
  • В целом, по крайней мере первые пару недель, получается хороший буст по скорости и настроению

Отрицательные эффекты:

  • Размывается граница между отдыхом и работой. Иногда все же требуется на пару дней забыть о проекте
  • Постоянно приходится помнить о проекте. Иногда это весело, один раз я вспомнил об отсутствии коммитов в 23:56, и вполне успел реализовать конкретную фичу, но большей частью это просто неудобно
  • Начинается некоторое растягивание задач по времени. Например сначала открывается задача в багтрекере, а на следующий день закрывается. Еще получается удобно кодить около 11 вечера. Тогда можно сделать коммиты сразу за 2 дня
  • Не учитывается физический вклад. Конечно можно открывать и закрывать задачи вида «Сходить поставить программу на счет», но этому не место в моем уютном багтрекере

Забавные моменты:

  • Один раз пришлось все делать на экстрим-скорости: я вспомнил о BSA-Analytics в 23:56. К счастью, я весь день крутил в голове что и как надо сделать, поэтому успел за 15 секунд до полуночи
  • Три недели назад я остался без клавиатуры на ноуте, поэтому пяток коммитов был полностью сделан с помощью экранной клавиатуры
  • Один из коммитов пришлось по техническим причинам делать по дороге в Москву с экранной клавиатуры и мобильного интернета

Тест выцветания чернил: результаты

Полгода назад я начал тест выцветания чернил. В декабре ко мне доехала еще пара ручек, которые я внес в список.

Наибольший интерес для меня представляет Pilot G2

Около месяца назад я убрал лист с подоконника, где он был неоднократно залит/высушен/болтался под ветром и снегом. С тех пор лист валялся в темном ящике, а мне было лень написать о результатах.

Читать далее

Система шестилетней давности

Когда-то очень давно когда я учился в школе, у меня не было ноута. При этом уже тогда мне нравился линукс, который я таскал с собой на внешнем жестком диске. Когда я приходил на кружок по программированию, я доставал специальный mini-cd диск на 200 мегабайт, содержащий загрузчик Grub 0.97. Школьные машины не умели грузиться по USB, но имели cd приводы.

В те времена я еще не очень хорошо был знаком с внутренним устройством линуксов, поэтому мне пришлось перебрать несколько дистрибутивов, чтобы понять какой из них умеет загружаться с внешнего жесткого диска. Я все еще помню свои результаты:

  1. ASPLinux — крутой инсталлятор, проблемы с софтом, очень старая (уже по тем временам) версия дистрибутива
  2. Mandriva — сидел около года, наверное. Но с диска она грузиться не умела
  3. Fedora — норм система, но чем-то не понравилась
  4. ArchLinux — графику не завезли, при нажатии бекспейса на консоли TTY раздавался страшный звук из динамиков, который меня сильно пугал
  5. Gentoo — поставил, только клавиатура не работала. И графики не было. А так в принципе норм, приглашение логина появлялось. Зато без initramfs грузился
  6. OpenSUSE — грузилась с диска, работала, имела пакетный менеджер
  7. Ubuntu — с диска не грузилась, судя по всему из-за автоустановки и настройки проприетарных драйверов на видеокарту.
    Раздражала из-за своей простоты. Тем не менее, в тем времена Cannonical рассылала бесплатно свои диски, и у меня была идея фикс на следующем релизе (10.04) попросить их прислать мне пару дисков.
    К сожалению, именно начиная с этой версии они эту халяву прекратили
  8. Kubuntu — сидел около полугода, норм система
  9. Mint — сидел года два. Любимая система до арча. Отличалась открытием менюшки аналогичной Win по 4-5 секунд. С загрузкой процесса python2 на 100%. Поэтому я не люблю питон

Короче, на диске у меня стояла OpenSUSE. В СУНЦе диск благодаря одалживанию различным нехорошим личностям раздолбался (а это не самая легкая затея раздолбать ADATA SH93), и до недавних пор пылился, потому что я разобрать его не мог. Но сейчас у меня дошли руки, поэтому с помощью ножа, топора, рычагов и грубой силы я раздолбал внешнюю неразбираемую оболочку и, неожиданно, извлек вполне рабочий Western Digital Blue 500GB.

Читать далее

ThinkPad P50 — мощь без компромиссов

Предыстория

С недавних пор меня перестал устраивать Acer Aspire S7. Конкретно — откровенно перестало хватать 4Gb памяти. Любая активность, вплоть до открывания нескольких «правильных» вкладок chrome, выливалось в использование swap со всеми вытекающими. В принципе, с учетом SSD, скорость swap’a была вполне приемлемой. На постоянно жить на swap’е c последующим перегревом — не вариант. Я просто боялся в какой-то момент остаться со сгоревшим ноутом. SSD можно было бы конечно дернуть, но его стоимость (а он был достаточно странным — планка представлялась рейд массивом, количество сброшенных данных не считалось) была несравнима со стоимостью всей машины. Поэтому он был торжественно продан.

Поиск нового ноута

Основные критерии:

  1. Экран не меньше FullHD
  2. Приличная батарея
  3. Либо 4 ядра SkyLake, либо 2 ядра KabyLake
  4. Отсутствие видеокарты AMD
  5. Возможность установки не менее 16 гигов оперативки, лучше 32
  6. Возможность установки SSD. Его, конечно всюду можно поставить, но все же…

Список интересных моделей:

  1. Dell XPS 15. Красивый и легкий ноут. Хорошая батарея и процессор. К сожалению, дико дорогой в нормальной конфигурации — 130 тысяч, из-за границы никак не провезти без возни с таможней. Вдобавок к этому — он перегревается при нагрузке. Если бы был готов отдать столько денег — купил бы его.
  2. ThinkPad t460/t560. Хорошие машинки. Единственная претензия — слабоват процессор.
  3. Ряд игровых ноутов. Две основные проблемы: никакущие аккумуляторы, уродливый дизайн.

Но победил ThinkPad p50. Младшая модель — 20ENCTO1WW.

Последняя фотка Aspire S7 на линуксе


Читать далее

Тест выцветания чернил

Летом я наткнулся на крайне занимательный блог penfan.ru. Конкретно меня зацепил его тест на выцветание, который, судя по всему, является уникальным в рунете.

Ручки — одно из самых безобидных и дешевых увлечений, поэтому я торжественно провозгласил себе любителем ручек и приступил к закупкам. К сожалению, самая крутая ручка всех времен и народов (Pilot Cavalier, если кто не в курсе) какого-то черта снята с производства в своем оригинальном виде. Вместо нее была взята Platinum SBTB, которая шикарна всем, кроме того что в нее нельзя запихать гелевые стержни Pilot…

Но не суть. Не опровергая результаты великих, постараемся их дополнить. Все интересующие меня ручки и стержни доехали, для массовки добавлены все те noname ручки, которые реально купить в России, и тест начался.

Мой почерк красивый, примите это в качестве аксиомы

Мой почерк красивый, примите это в качестве аксиомы


Читать далее

Чиним Aspire S7 с помощью березы и топора

У меня давно был раздолбан разъем питания на ноуте. Ну как раздолбан, я всего лишь один разок уронил его на пол с полуметровой высоты аккурат на воткнутый китайский штекер. Который был слишком длинным.

В общем, разъем внутри треснул, и с нормальным БП работать по-хорошему не захотел. По традиции, развлекаюсь сам. EBay, 8 дней ожидания, 450 рублей, часок на почте и приготовления завершены.

Новый разъем

Новый разъем

Читать далее

Программирование на ВМК

Я очень часто повторяю, что на ВМК не учат программировать. Большинство людей такие фразы абсолютно не понимают, а объяснять мне обычно лень. Но вот недавно я увидел код ВМКшника, в котором была задача прочитать бинарный файл. Задача несколько осложнялась тем, что ожидаемый (а может быть и требуемый) язык реализации был C/C++. Как бы вы считали бинарный файл? Я бы открыл его fopen’ом (плохо знаю плюсы, надо бы, конечно, какой-нибудь datastream использовать). А по возможности использовал бы Qt, который позволил бы удалиться на более высокий уровень, почти не потеряв в скорости. Этот товарищ использовал системные вызовы. Он читал файл через open и read. Это ужасно. Совершенно не к месту системные вызовы, которые еще и медленнее будут, если что-то пойдет не так с кешами. А если хочешь кеши — придется их самому написать. Может возникнуть вопрос — а зачем использовались системные вызовы то? Ответ прост — нам рассказывали только их. Поэтому, если вы видите странный код, изобилующий системными вызовами вместо нормальных библиотечных функций — перед вами с большой вероятностью ВМКшник. Этот пример не единственный. Я уже насмотрелся на однострочные комментарии «конструктор», «деструктор», «выделение памяти», «освобождение памяти», а также удаление дефолтных операторов присваивания, дефолтных конструкторов и прочей ереси, которую удалять совсем не обязательно.

Короче, учат не тому. А после просмотра подобного кода сразу видно какие курсы посещал человек. И не дай бог ему понравился ассемблер…

О чужом коде

Пару лет назад я посмотрел код OpenSSL. Он был ужасен. Особенно меня поразила примерно такая конструкция:

if (0) {
    L1:
    // some code
}

if (condition)
    goto L1;

Через некоторое время я решил что конструкция в принципе нормальная. А прочие ужасы кода свалил на то, что он написан математиками.

Но сейчас я решил расковырять другой продукт. Дело в том, что в CoolReader при ресайзе окна в управлении kwin происходит неприятный баг — он перематывает текст на конец. Это невероятно разражает — по сути единственный выход, это не ресайзить окно. Я решил найти в чем же проблема и полез в исходники. Исходники оказались страшноваты, но следующий код — это…

#define XS_IMPLEMENT_SCHEME 1
#include "../include/fb2def.h"

#if 0
void SaveBase64Objects( ldomNode * node )
{
    if ( !node->isElement() || node->getNodeId()!=el_binary )
    return;
    lString16 name = node->getAttributeValue(attr_id);
    if ( name.empty() )
    return;
    fprintf( stderr, "opening base64 stream...\n" );
    LVStreamRef in = node->createBase64Stream();
    if ( in.isNull() )
    return;
    fprintf( stderr, "base64 stream opened: %d bytes\n", (int)in->GetSize() );
    fprintf( stderr, "opening out stream...\n" );
    LVStreamRef outstream = LVOpenFileStream( name.c_str(), LVOM_WRITE );
    if (outstream.isNull())
    return;
    //outstream->Write( "test", 4, NULL );
    fprintf( stderr, "streams opened, copying...\n" );
    /*
     lUInt8 dbuf[128000];
     lvsize_t bytesRead = 0;
     if ( in->Read( dbuf, 128000, &bytesRead )==LVERR_OK )
     {
     fprintf(stderr, "Read %d bytes, writing...\n", (int) bytesRead );
     //outstream->Write( "test2", 5, NULL );
     //outstream->Write( "test3", 5, NULL );
     outstream->Write( dbuf, 100, NULL );
     outstream->Write( dbuf, bytesRead, NULL );
     //outstream->Write( "test4", 5, NULL );
     }
     */
    LVPumpStream( outstream, in );
    fprintf(stderr, "...\n");
}
#endif

А вот так элегантно решается вопрос об индикаторе батареи: