Vikhrmodels/habr_qa_sbs huggingface dataset:
Вопрос: Как получить график громкости аудио без его воспроизведения?

Лучший ответ:
Декодирование аудиоданных из аудиофайла с помощью WebAudio Api можно действительно делать без воспроизведения этого файла. А это значит, что это может происходить по ходу загрузки страницы, и клики при этом не нужны.<html>
<head>
<meta charset="utf-8">
<title>Визуализатор</title>
<style>
#canvas{
    position: absolute;
    top: 50px;
    left: 0px;
    background: #333;
}
#progress{
    position: absolute;
    top: 50px;
    left: 0px;
    background: rgba(255, 155, 0, 0.5);
    width: 0px;
    height: 256px;
}
</style>
</head>
<body bgcolor=#444>
<audio id=audio src="sound.mp3" controls></audio>
<canvas id=canvas width=512 height=256></canvas>
<div id=progress></div>
<script>
var audio = document.getElementById("audio");
var ctx = canvas.getContext("2d");
var color_L = "#7cf", color_R = "#f7c"; // Цвета осциллограмм левого и правого стереоканалов
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
audio.onplay = function(){b = setInterval(function(){progress.style.width = Math.floor(audio.currentTime / audio.duration * canvas.width) + "px"}, 100)};
audio.onended = function(){ 
    this.currentTime = 0;
    clearInterval(b);
    progress.style.width = "0px";
}
var source = audioCtx.createBufferSource();
var request = new XMLHttpRequest();
request.open('GET', audio.src, true);
request.responseType = 'arraybuffer';
request.onload = function(){
    var audioData = request.response;
    audioCtx.decodeAudioData(audioData, function(buffer){
        source.buffer = buffer;
        data_L = buffer.getChannelData(0);
        data_R = buffer.getChannelData(1); // Если аудиофайл моно - поменяйте в этой сроке единицу на ноль.
         // При несоответствии количества стереоканалов - ошибка в консоли и код не работает.
        for(var i = 0; i < data_L.length; i++){
            var x = Math.floor(i / data_L.length * canvas.width);
            var L = data_L[i] * canvas.height / 4;
            var R = data_R[i] * canvas.height / 4;
            if(Math.floor(i / 16) == i / 16){ // Число 16 для больших аудиофайлов лучше побольше. Нужно подбирать.
                ctx.fillStyle = color_L;
                ctx.fillRect(x, canvas.height * 0.25 + L, 1, -L);
                ctx.fillStyle = color_R;
                ctx.fillRect(x, canvas.height * 0.75 + R, 1, -R);
            }
        }
    },
    function(e){"Error with decoding audio data" + e.err});
}
request.send();
canvas.onmousedown = progress.onmousedown = function(e){
    progress.style.width = e.pageX + "px";
    audio.currentTime = e.pageX / canvas.width * audio.duration;
}
canvas.ondblclick = function(){audio.play()};
ctx.fillStyle = color_L;
ctx.fillRect(0, canvas.height * 0.25, canvas.width, 1);
ctx.fillStyle = color_R;
ctx.fillRect(0, canvas.height * 0.75, canvas.width, 1);
</script>
</body>
</html>

Худший ответ:
Вот, как вариант, раз вы хотите делать это не во фронте. Не знаю насколько актуально. На выходе вы получите png-картинку
Вопрос: Удалять ли ненужные записи в базе данных или оставлять?

Лучший ответ:
Я бы поступил следующим образом:
1. создать ёще одну таблицу с идентичной структурой
2. при удалении переносить из основной таблицы в архив

Преимущества:
1. основная таблица остается компактной
2. при необходимости можно всегда восстановить данные

Худший ответ:
А смысл их оставлять? Они ведь попросту ненужный мусор. Но в плане реализации можно сделать срок действия для восстановления истёкшего объявления 7 дней. Если оно не будет восстановлено, то удаляется из базы данных.
Вопрос: Как использовать Symfony\Messenger без фреймворка?

Лучший ответ:
По статье всё верно описано. Там в контейнер добавляется 
* Container->addCompilerPass(new MessengerPass());

Я просто забыл вызвать компиляцию контейнера 
* Container->compile();

Худший ответ:
Вот, написал статью на эту тему на хабре 
Там всё подробно описано
Вопрос: Как устроить на первую работу в сферу frontend'a?

Лучший ответ:
Устраивался я 21 год назад, не фронтом и даже не web-разработчиком, так что экспертом приглашать меня не стоило. Но раз уж пригласили, то поделюсь опытом найма. Стажёров и джунов почти никто не нанимает. При этом в ИТ сейчас прёт всё больше народа, количество соискателей уже в сотни раз больше, чем вакансий для начинающих. Отсюда относительно высокие требования к соискателю при достаточно низких зарплатах. Поэтому первое, что нужно - везение. Можно быть сколь угодно крутым, но затеряться в потоке. Второе - нужно хорошо составленное резюме и пет-проект. И последнее по очереди, но не по значению - надо быть лучше остальных ста соискателей. Это не сильно сложно, большинство из них - жертвы курсов и видео-уроков. Имея всё вышеперечисленное, придётся сделать очень много откликов, сходить на очень много собеседований и потом поработать годик за еду. После каждого проваленного собеседования просите обратную связь. Зубрите то, что спрашивали. Подтягивайте то, с чем не справились.

Худший ответ:
Сделай сайты всем друзьям знакомым родственникам  и денег поднимешь и опыта наберёшься
Вопрос: Как в Mikrotik направить в VPN определенные сайты?

Лучший ответ:
Нужно было поставить 
/ip settings rp-filter=loose

Стояло в strict

Худший ответ:
Fasttrack там не мешает?

А вообще за сменой айпи и так придется следить: он (во всяком случае на моих hap (ac) lite) хватает ip по домену и заносит в список его, не сам домен
Вопрос: Как выполнить backup базы данных mysql запросом?

Лучший ответ:
Очень теоретически можно организовать бэкап БД "одним запросом". И это будет запрос
CALL stored_procedure(@datatbase_name);
А вот в хранимой процедуре будет дофига запросов. Нужно будет из INFORMATION_SCHEMA получить список всех имеющихся в БД объектов и организовать копирование информации во внешний файл (причём для каждой таблицы придётся делать два файла - один со структурой, второй с данными). А ещё надо не забыть про процедуры, функции, триггеры... в общем, задачка весьма нетривиальная. Лучше даже не начинать.

Худший ответ:
Другая  база, другие правила
https://dev.mysql.com/doc/mysql-backup-excerpt/5.7...
Вопрос: Как найти хаб в сети, если не знаешь где он?

Лучший ответ:
вытащить патчкорды из тех двух компов, и дернуть за них посильнее

Худший ответ:
У активного концентратора должно быть питание. Обычно розетки не прячут.
Но есть и пассивные разветвители, вот его точно не найти.
Проше заново проложить. Тогда и возможно потерю найдёте.
Вопрос: Как реализовать очередь в node js?

Лучший ответ:
Как правильнее было бы реализовать это?
Не изобретать велосипед, а погуглить готовые решения для очередей.
Беглый поиск:
https://www.npmjs.com/package/queue
https://github.com/bee-queue/bee-queue
https://levelup.gitconnected.com/how-to-implement-...
Ну и всякие там rabbitmq и т.п.

Худший ответ:
https://github.com/OptimalBits/bull
https://optimalbits.github.io/bull/

Используйте это или посмотрите, как реализована библиотека.
Вопрос: Как организовать хранение данных для новостной ленты социальной сети?

Лучший ответ:
2. Готовить ленту для каждого пользователя отдельно. То есть возникает в какой-либо сфере событие, его нужно записать в ленту для миллиона подписчиков.Беда этого варианта в том, что из миллиона подписчиков половина не заходили в ленту полгода+, ещё 200 тысяч не заходили месяц+, ещё 200 тысяч не заходили неделю+, а ваша БД всё это время бесполезно молотит для всего миллиона.

Здесь нет простого решения (в соцсетях вообще много непростого). Вам нужно как минимум комбинировать первый и второй метод (а может быть ещё и какой-то третий и какой-то четвёртый). И чтобы делать это оптимально (не требуя на миллион подписчиков столько же мощностей, сколько Вконтактик потратил бы на 10 миллионов подписчиков), потребуются действительно умные алгоритмы, а не только совет насчёт подходящей СУБД. Навскидку, для событий от друзей больше подходит второй метод, а для событий сфер - первый метод. Но это не точно. Можно применять второй метод только для тех, кто заходил не больше суток назад и т.п.

Худший ответ:
Как уже указал hint000 первый вариант можно использовать только очень ограниченно. Для второго лучше взять что-нибудь документо-ориентированное или мульти-колоночное, что позволит денормализовать структуру данных. Т е вам нужно хранить некое представление "обобщённой ленты" (возможно отдельно для каждой сферы, что бы потом это можно было шардировать) и там будут лежать эвенты в каждом из которых может быть записано много разной информации. Возможно какие то данные пользователей, для формирования их персональной ленты в момент запроса. В принципе и на базе postgres можно организовать такую таблицу, c большим количеством полей, плюс postgres умеет класть в колонки json, что может помочь. Но в любом случае лучше применить паттерн CQRS и исходные данные хранить нормализованными, а при их изменении бросать эвент, который пойдёт в RabbitMQ или Kafka и будет обрабатываться пулом инстансов, обновляющих записи в лентах. А раз так, то там вообще можно взять что-нибудь типа elastic search. На чтение она должна быть очень быстрой.
хаос в разрешении всевозможных ситуаций: подписок, отписок, удалении постов и так далее.
Наибольшую боль, как мне кажется, доставит удаление/блокировка контента, т к оно подразумевает обновление большого количества информации во всех лентах куда попало удаляемое. Вы можете пойти на компромисс и сделать, как делают многие - удаленные посты приходят в ленте как заглушка. В этом случае нет необходимости удалять их идентификаторы из лент, достаточно просто не выдавать их при запросах по айди. Плюс не ломается пагинация и не нужно изобретать велосипеда с бесконечными прокрутками (хотя если маркетойды настаивают, что так лучше, то нам же легче ))
Вопрос: Unity выдает ошибку: Assets\script\playerController.cs(20,31): error CS1061: 'float' does not contain a definition for 'GetAxis'. Как это исправить?

Лучший ответ:
Совсем новичок просто)
сначала стать не новичком, а потом открывать юнити

Худший ответ:
muveInput = muveInput.GetAxis("Horizoontal");
переменная muveInput  не знает что ей делать, когда ей говорят сделать GetAxis()
скорее всего заработает, если ей сказать, стать равной значению возвращаемому методом GetAxis(), которая кстати как раз float
Вопрос: Как устроиться консультантом по ИБ?

Лучший ответ:
Зайдите на hh.ru.
Вколотите "консультант ИБ" в поиск.
Смотрите требования в вакансии.

И да:
Опыт администрирования сервера Касперского и СЗИ Блокхост. Установка СКЗИ криптопро, криптоарм, плагины для браузеров для работы с криптой, настройка ЭЦП с помощью указанных выше программ.
Я это делал, когда был эникейщиком и единственным сисадмином в конторе. Вряд ли с таким бэкграундом можно на что-то рассчитывать.

Худший ответ:
Как раз недавно был интересный ролик на разведопросе. У гостя есть сайт услуг.
Вопрос: Как создать n количество переменных?

Лучший ответ:
Это называется массив.

Худший ответ:
Список/массив на n элементов.
Вопрос: Как правильно импортировать проекты в Android Studio?

Лучший ответ:
Там 2 андроид приложения и бакенд написанный на джава, который где-то еще нужно разместить в сети.

Легаси 7 летнее. Студией вы его автоматом не обновите
'com.android.tools.build:gradle:1.1.0'
compileSdkVersion 21
minSdkVersion 14

Проще начинать новый проект с нуля и переносить код по частям, заменяя устаревшие вещи .
Фактически там почти все придется переписать

Худший ответ:
Проекты старше 1 года проще создавать с нуля.
1. Создаёшь пустой проект
2. Копируешь из старого проекта манифест и код из src в новый проект вместе с ресурсами
3. А вот gradle-файлы надо копировать очень аккуратно.
Желательно на каждом этапе создавать отдельную ветку в гите с возможностью отката.

Андроид не поддерживает обратную совместимость и это вечная боль для разработчиков
Вопрос: Почему верстальщики хотят верстать из .psd и не хотят Фигму? Что можно им предложить?

Лучший ответ:
Лентяи, которые не хотят учиться. Ищите других.

Худший ответ:
Люди привыкли работать с photoshop. Пока нейронные связи в мозгу новые сформируются при обучении работы с figma - пройдёт время, а всё это время верстальшики будут тормозить процесс.
Вопрос: Как можно проварьировать стандартные части программы Hello World на C#?

Лучший ответ:
хеллоуворд видится как какой-то буддистский коан.
Минимальный современных хеллоу ворлд выглядит так:
Console.WriteLine("Hello world!");

Чтобы разобраться во всех следующих пунктах тебе следует продолжать изучать (хоть по курсу, хоть по книге), иначе всё расписывание само по себе потянет на небольшую книгу, или хотябы брошюру, и при этом врядли как-то тебе поможет:

1. Можно просто убрать этот конкретный using, используя global usings или используя полные имена типов
2. Можно не писать namespace или написать любой свой собственный. Или можно использовать file scoped namespace
3. Можно придумать своё имя класса, можно сделать его статичным, можно сделать явно приватным или публичным.
4, 5, 6.  Main (точка входа) обязан быть статичным. Другие методы могут быть не статичными.
Main можно сделать публичным или приватным, можно дать другое имя, но тогда придётся в опциях компилятора указать, какое имя.
Main можно сделать асинхронным - тогда вместо void или int (Да, он может возвращать int) будет Task или Task
7,8,9. string[] args можно не указывать, или дать этому параметру другое имя (не args), но принимать что-то иное нельзя
10,11. Это уже относится к телу метода и оно может быть любым. Но вместо Console.WriteLine можно написать полное имя - System.Console.WriteLine или сделать using static System.Console и тогда можно будет написать просто WriteLine

Худший ответ:
В дополнение к комментарию выше:
>>1. Можно просто убрать этот конкретный using, используя global usings или используя полные имена типов
Это избавит от одного и того же using в формах/классах. 
global using - это в рамках всего решения.

От себя: если у вас там не только Привет-Мир будет, а что-то, что может вызвать ошибки, тогда не void, а int - вы сможете возвращать код ошибки. То есть 0, если все прошло без ошибок.

У себя в проектах использую передачу переменных по ссылке, так что иногда у меня в таких аргументах и код ошибки, и описание, а сама функция, например, возвращает System.Data.DataView, и тогда если переданная по ссылке переменная iError больше нуля - тогда я даже не обращаюсь к результату выполнения: он, скорее всего, null. Вообще, в функции я передаю много чего по ссылке, их может быть сколько угодно. Если я в функции форматирую что-то в HTML, я могу по ссылке вернуть в переменную и обычный текст.
Вопрос: Как сделать сертификат для второго сервера?

Лучший ответ:
На сервер2 ставите nginx и делаете proxy_pass на сервер1. DNS должен указывать на сервер2, и ssl-cертификаты для домена должны стоять на нём же. Трафик между серверами можно шифровать хоть самоподписными сертификатами.

Худший ответ:
Сертификат выдаётся для домена. Если оба сервера обслуживают один и тот же домен - копируйте его на оба сервера. Ну и proxy_pass со второго на первый, конечно.

Если домены разные - делаете под них сертификаты, и копируете на соответствующие сервера, логично же. Хотя нет, на первом сервере сертификат со второго тоже нужен, файлы то на нём.
Вопрос: Что использовать для Desktop UI на C#?

Лучший ответ:
Ежели нужно что-то совсем хисптерское, кросс-платформенное, на переднем краю технологий, то MAUI конечно же.

А если серьезно и у вас только windows то возьмите WPF.

Худший ответ:
Выбор не слишком большой: WinForms/WPF/Avalonia. Хотите WPF - используйте WPF.
Вопрос: Какой максимальный диапазон чисел в for i in range?

Лучший ответ:
Господи, ну нельзя заниматься программированием с такими представлениями о логике. 
Причем не о какой-то там хитрой математической логике, а о логике своих действий. 

Неужели так трудно проверить свое собственное утверждение? 
for i in range(200000, 500000):
    if (i < 200005):
        print(i)
    if (i == 200005):
        print('...')
    if (i > 499995):
        print(i)

Где здесь 0? Где здесь 208?
С чего вы взяли, что эти цифры вообще берутся из этого цикла, а не откуда-то еще?

Программист всегда должен проверять свои догадки. 
И если они не подтвердились, то искать другое объяснение своим проблемам.

Худший ответ:
К максимальному диапазону ошибка отношения не имеет.
Проблема прежде всего в том, что у вас один, притом общий Exception на 300к итераций содержащих запросы по интернету.
И если на условной стотысячной итерации произойдет какая-то ошибка (начиная от глюка ОС/оборудования/ошибки у провайдера из-за которой запрос в принципе не дойдет и заканчивая "неправильным" ответом от сайта), то остальные 200к итераций просто не случатся.
Вопрос: Какое устройство использовать для замыкания контактов на плате управления откатными воротами через WiFi?

Лучший ответ:
Простите, может я ошибаюсь, но зачем вам  Raspberry Pi + WiFi-свисток ? 
Насколько я знаю, существует уже готовый модуль управления воротами по Wi-Fi DOORHAN SMARTCONTROL-2. https://doorhan.ru/spravka/data-test.php?data=Smar... 


Инструкция...
https://doorhan-moscow.com/upload/iblock/995/Smart...

Худший ответ:
Sonoff SV или любое аналогичное реле с сухими контактами решит Вашу проблему. Только вот управлять воротами через интернет чревато, так что рекомендую прошить на него альтернативную прошивку для отвязывания от китайских серверов.
Вопрос: Как перенести папку Users на другой диск?

Лучший ответ:
Про профиль не в курсе, но вот физическое расположение стандартных пользовательских каталогов легко настраивается в их свойствах.
Найдите самые крупные и настройте для них новое расположение.

Худший ответ:
Вот тут описано: https://www.top-password.com/blog/move-the-entire-...
Я примерно так же делаю еще со времен WindowsXP. 
Но я не переношу профиль Default и Public, как описано в статье, а пользовательский профиль создает винда сама в новом месте (данные во вновь созданный профиль, потом копирую руками). В профилях полно ссылок и при простом копировании всего каталога ссылки останутся указывать на старые места (а этого нам не нужно). 

Для того что бы не было проблем со ссылками действуйте по моему методу.
На новом томе создаете пустую папку Users (имя папки не принципиально) с такими же правами и наследованием как у папки c:\Users. Далее указываете путь в параметре реестра ProfilesDirectory (смотри ссылку), Public и Default оставляете без изменений. 
Что бы винда создала новый профиль надо удалить ветку реестра старого профиля пользователя. Ветки реестра  профиля находятся в разделе реестра ProfileLists (смотри ссылку) и имеют вид S-1-5-2-1-..., находите ветку интересующего вас пользователя и удаляете ее целиком (если страшно, можно ветку переименовать - добавьте к ней префикс). После перезагрузки винда создаст новый профиль в новом месте. Переносите данные из старого профиля в новый. Удаляете старый профиль. Все!
Все профили новых пользователей будут создаваться на новом месте. При этом профили Public и Default будут находится на прежнем месте, так что каталог c:\Users не удаляйте. Т.к. профиль создан самой виндой с нуля, то все ссылки внутри профиля будут корректные.
Вопрос: Как сделать в Go, чтобы какая-то goroutine выполнялась циклично до тех пор, пока state не станет false?

Лучший ответ:
В вашей реализации надпись "I am doing this!" будет показана только один раз, т.к. вы пишите всего 1 раз в канал, а потом выполнение заблокируется на чтении данных из канала, т.к. там данных не будет.

То, что вы хотите сделать можно сделать вот так:
package main

import (
    "log"
    "time"
)

func doSomethingEvery5Seconds(ch chan bool) {
    log.Println("Started!")
    for {
        select {
        case <-ch:
            return
        default:
            log.Println("I am doing this!")
            time.Sleep(1 * time.Second)
        }
    }
}

func main() {
    ch := make(chan bool, 1)
    go doSomethingEvery5Seconds(ch)
    time.Sleep(15 * time.Second)
    close(ch) // Останавливаем спустя 15 секунд
}

Худший ответ:
Вот пример работы с маятником:
https://gobyexample.com/tickers
Похоже на то как указал Евгений Мамонов , но вместо time.Sleep(1 * time.Second) значения берутся из канала маятника, которые будут блокироваться на указанное время.
Вопрос: Как удалить все классы, начинающиеся с определённой подстроки?

Лучший ответ:
Array.from(el.classList).forEach(n => el.classList.toggle(n, !!n.indexOf('modal--')));
или

el.classList.remove(...[...el.classList].filter(n => n.startsWith('modal--')));
или

for (let i = el.classList.length; i--; ) {
  if (el.classList[i].search('modal--') === 0) {
    el.classList.remove(el.classList[i]);
  }
}
или

el.className = el.className.split(' ').filter(n => !/^modal--/.test(n)).join(' ');
или

el.className = el.className.replace(/ ?modal--\S*/g, '').trim();

Худший ответ:
Получить массив с именами классов,
отфильтровать начинающиеся на искомую подстроку,
удалить только их:
snippetчерез 3 секунды удалятся классы, начинающиеся на "habr--"
Вопрос: Как правильно составить микро разметку по schema.org?

Лучший ответ:
Скорее всего, конкретно под музей нету микроразметки схема. Я не встречал. Вам могут такие разметки пригодиться:

1. https://schema.org/Organization - описание организации.

2. https://schema.org/Review - отзывы посетителей

3. https://schema.org/Event - микроразметка событий. Можете с помощью нее оформлять предстоящие выставки, ночь музеев и прочее.

4. https://schema.org/ImageObject и https://schema.org/VideoObject - этим оформить картинки и видео на сайте.

Забыл написать. Если примеры стандартной документации, что я привел вам непонятны, то можете каждую по отдельности загуглить и найдете примеры как исполнить.

Худший ответ:
Лучше никак, поставил себе, никаких плюсов и изменений нигде не увидел, траффика как было, столько и осталось кроме галочек в сервисах "seo анализ сайта
Вопрос: Когда стоит начинать учить фреймворки?

Лучший ответ:
Ну, по-хорошему, ещё рановато.
Всё-таки, фреймворки служат для ускорения разработки веб-приложений, а не одностраничных черновиков. 
При чем это очень важный момент.
Не использовав в своей работе всё, что требуется при разработке веб-приложения (в том числе безопасность, следование рекомендациям протокола НТТР, валидация данных, и примрно ещё десяток нужных вещей) - то не сможешь реально понять, как много фреймворк делает за тебя.

Худший ответ:
Мое мнение - этот этап переходный. В эру микросервисов чем меньше дредноут - тем лучше. Раньше казалось "будем писать на ларавель - всегда найдем специалистов по ларавелю". Некоторые и сегодня так думают. Другие - следуют мысли "как хочешь так пиши, а вот тесты должны пройти". А те кто ещё хитрее и вовсе сделают тебя виноватым за выбор одного из фреймворков, причем если все будет работать - то молодцы будут они, а если ты не справился - то дурак ты, вот и решай - быть тебе с фреймворками или головой шевелить.

ООП, композер и пакеты - наш выбор. Дредноут где "всё включено" и без бутылки водки ничего нельзя отключить потому что "оно так настроено" - уже нет.

Подымая мысль о том, что фреймворк заботится о безопасности делая много вещей из коробки - добавлю, что в эпоху тех самих микросервисов ты либо будешь учить микро-фреймворк, который этого не делает, либо тебе скажут, что "на этом сервисе у нас только авторизация, а ты сюда зачем-то прикрутил троттлинг, ддос защиту, csrf защиту, защиту от иньекций и всё это вместе". Это все сжирает драгоценные миллисекунды и что важно - может быть сделано на других слоях тоже. В какой-то конторе крутой девопс способный сделать это на линуксах, в другой конторе были талантливые программисты, которые написали слой авторизации, который это уже делает за тебя и девопс это обернул так, что штука, которая разворачивает сервисы при каждом запросе это сама делает для тебя, а твое приложение делает это ещё раз.

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

Лучший ответ:
Любой, предоставляющий VPS/VDS.

Худший ответ:
Добрый день.
Если приложение действительно простое, то подойдет любой VPS / VDS.
Однако, замечу, что было бы неплохо провести профилирование и глянуть на объем потребляемой оперативной памяти и т.д.
Также при выборе хостинга стоит учесть тот факт, что могут быть проблемы с оплатой услуг зарубежных провайдеров. А так я бы посоветовал Hetzner (немецкий) из разряда дешево-сердито.