Pull to refresh
64
0
Павел @RPG

User

Send message

У меня Андроид студия столько же жрет, и никаких расширений ставить не пришлось:) Если мы говорим про экономию памяти — однозначно vim. Или Geany, он память не жрет и довольно много из коробки умеет.

Добавлю ещё отличные плагины:


  • Color Highlight — показывает цвет цвета прямо в редакторе
  • EditorConfig — для поддержки одноименного формата
  • PlantUML — диаграммы прямо в редакторе
  • Script Commands — если лень писать свои плагины, можно цеплять абсолютно любые собственные скрипты к редактору
    Главное, что нет необходимости ставить 3 IDE, если время от времени нужно править код на Java/JavaScript/ObjectiveC/C++.

Хотя и сам не прочь крутить подобные портянки, хочу предупредить читателей, этот код — не пример для подражания. Выход за границу 80 символов — сама по себе проблема, и если скрипт "причесать" до читаемого состояния, то в нём будет уже не 9, а без малого сотня строк. И гарантировать, что этот скрипт не развалится от случайно затесавшегося неформатного файлика, в отличие от настоящего парсера, невозможно. А когда он развалится, отладка превратится в ад (если этот факт вообще кто-то заметит).


Также для уменьшения времени работы, количества временных файлов да и просто вероятных ошибок, в Bash есть замечательная конструкция:


while read -r line; do
  echo $((line**2))
done < <(seq 123)

В отличие от command | while ...do ... done она не создаёт новый сабшелл и позволяет избежать ошибок, связанных с потерей переменных.

чтение из разных конфигов, где я считываю значение переменных

Если позволяет формат конфигов — то не знаю ничего быстрее чем source config.cfg, всё что было внутри конфига превратится в переменные баша. Такой способ используется повсеместно в initscripts. Все эти ifcfg-eth0 в RHEL по крайней мере — по сути шелл-скрипты.


Ещё один способ, который годится для перегона нестандартного формата конфига — eval "$(sed ... config.ini)". Сед приводит конфиг в башеподобному виду, eval превращает в переменные.


Обычно так делают студенты домашку, так как им показали ограниченный набор базовых команд.


VAR1=$(cat file.cfg | grep var | cut -f2 | sed 's/"//')
… и так десять раз

Дело в подготовке данных (вы вызываете cut 1000 раз, а я один раз но для 1000 строк).

Если не можете выиграть битву, поменяйте поле:


#!/usr/bin/env bash

# prepare data
for A in {1..1000}; do
    STRING+="Name$RANDOM Date$RANDOM Shell$RANDOM"$'\n'
done

echo "using cut"
time cut -d " " -f 3 <<<"$STRING" > /dev/null

echo "using shell"
time while read a b c; do
    echo $c
done <<<"$STRING" > /dev/null

# using cut
# real    0.006
# у меня медленный компьютер, результат с echo аналогичен тому, что предлагает автор
# using shell
# real    0.026

  1. Когда нужно обработать много данных — пайпы лучше.
  2. Единичные случаи — да, эффективнее использовать bash-измы. Обратная совместимость пострадает, но мы вас предупреждали.
  3. С другой стороны, измерять эти миллисекунды имеет смысл, только когда данных много, следовательно см. п. 1.

В последнее время cut работает хорошо. Не так давно в GNU coreutils cut работал так, что его обгонял awk.

Попробуйте memtest прогнать. Такой же «баг» ловили на Intel, тоже падал компилятор только на крупных проектах вроде ядра или gcc, оказалось — битая плашка памяти, заменили и всё прошло. Много потоков -> много памяти -> выше шанс словить битую ячейку.
Поделитесь, пожалуйста, источником «остальных мер» — думаю, другим читателям будет полезно.
.(){ bash -e "$1";}

Подарите джуниорам бесценные часы отладки:) Можно добавить более весёлую шутку на свой вкус.

И это вы ещё поверхность не поцарапали...


cd $dir
rm -fr *

Спойлер: представим, что $dir не существует или пустой.


file=/etc/passwd
foo() {
  # local file
  for file in /*; do # file теперь глобально видна всем
    :
  done
}
foo
# ой!
echo $file

copy_file_to_tmp() {
  cp "$1" /tmp # работает ровно до момента появления файла с названием "-f"
}

Тысячи их.


А ещё bash -ue script.sh.


В целом хорошо, что появляются обучающие статьи про баш, плохо то, что учат они не тому. И не учат делать отступы в скриптах.


P.S.


count=$(( $count + 1 ))
# так тоже работает
((count++))

P.P.S. В systemd поняли ошибку и переписали всё с шелл-портянок на Си. Но в последний момент всё равно что-то пошло не так...

У меня такая же есть на 32 Кб, всё думаю, может и правда сделать заметку "во что превратился мой .bashrc"?:)

а вы при этом знаете, в чем будет отличие от bash ./commands.txt?

лишний раз subshell не будет запускаться (вдруг и правда кому-то нужно)


серьезно? А чем вас не устроил ab?

тоже хотел узнать, что может быть проще ab, к тому же предлагаемый вариант ужасен — wget намусорит файлами вида index.html.*


И если уж на то пошло, сильно укоротить можно: seq 1000 | xargs -I{} -P20 wget -qO/dev/null ya.ru (да простит нас Яндекс)

В Shell другие правила экранирования спецсимволов, которые ls не учитывает. Более правильно экранирует printf %q. И всё же лучше не полагаться на это, а ls может оказаться без этих расширений (busybox). В идеале должно получиться вот так: $'troll\nfile'

Не сочтите за грубость, но это тоже не будет работать:)


touch 'troll'$'\n''file'

Навскидку, как это правильно можно было бы сделать в bash (на самом деле так делать не надо, но демонстрация проблем с экранированием символов в шелле исчерпывающая):


#!/bin/bash

FILES=()
SIZES=()
i=0
while read -rd $'\0' file; do
    FILES+=("$file")
    SIZES+=("$(wc -c < "$file") $i")
    ((i++))
done < <(find -mindepth 1 -maxdepth 1 -type f -print0)
for l in "${SIZES[@]}"; do
    echo $l
done | sort -n | while read _ n; do
    printf '%q\n' "${FILES[$n]}"
done

Это из коллекции "1000 и один способ выстрелить себе в ногу в Shell". Если вы всё ещё полагаетесь в скриптах на вывод команды ls, настоятельно рекомендуется к прочтению, и это тоже.


У некоторых людей такой юниксвейный подход к проектированию интерфейсов вызывает глубокую депрессию.

И всё ещё неправильно. В имени могут быть пробелы и даже переносы строк. Правильно — переписать всё на Си, что в ls и сделали.


Нет ничего удобнее, чем вбить ls -lrt и посмотреть последние изменения в каталоге. А ещё никто не мешает сделать удобные для запоминания алиасы:
alias ListFilesSortedByLastModificationTime='ls -lrt'

На самом деле, даже такая мелочь как потребление памяти "хелловордом" в Python крайне раздражает. Python, который ещё ничего не делает, съедает сразу 6 МБ. Если мне надо запустить сотню скриптов параллельно — это уже проблема. Или другой пример — минималка CentOS, куча демонов — postfix, imap, https, systemd, rsyslog, у всех потребление памяти ~ 6-10 МБ. И выделяется firewalld, который по сути ничего не делает и жрёт при этом 25 МБ. Подозреваю, тут уже не в интерпретаторе дело, а в каких-нибудь хэш-таблицах, сделанных через односвязный список...


Но вот что интересно, если 100 человек отправит в апстрим аналогичный патч, снижающий потребление ОЗУ, то возможно сообщество прислушается?

В большинстве случаев можно и без макросов обойтись, вот например шаблон, который ведёт себя также как и функция print в Питоне:


template print*(x: varargs[string, `$`], file: File = stdout) =
  var res = ""
  for i in x:
    addSep(res, " ")
    if i != nil:
      res.add(i)
    else:
      res.add("(nil)")
  file.writeLine(res)

или withFile, который сам закрывает дескриптор после выхода из блока:


template withFile*(filename, body) {.immediate, dirty.} =
  block:
    var outfile: File
    template put(x: varargs[string, `$`]) = 
      outfile.writeLine(x)
    if open(outfile, filename, fmWrite):
      defer: close(outfile)
      body
    else:
      raise newException(OSError, "cannot open: " & filename)

В результате Nim становится не намного многословнее баша.

А они и взяли pcre, но я никогда ещё такого медленного pcre не видел:


# 4.5 sec
import re
let exp = re"agggtaaa|tttaccct"
var c = 0
for line in "in.txt".lines:
  if line.find(exp) != -1:
    c += 1
echo (c)

# 2 sec
import pegs
let exp = peg"'agggtaaa'/'tttaccct'"
var c = 0
for line in "in.txt".lines:
  if line.find(exp) != -1:
    c += 1
echo (c)

# 0.2 sec
grep -cE 'agggtaaa|tttaccct' in.txt
# 0.4 sec
grep -cP 'agggtaaa|tttaccct' in.txt

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

Переписывал на Nim пару скриптов-парсеров (~1000 LOC) для собственных нужд с целью поднять производительность того же самого, написанного на Питоне. Привлекает анонсированные аналогичный синтаксис и сравнимая с C скорость, по факту — так и есть. Скорость разработки немного медленнее, так как до сих пор некоторых фишек не хватает, но благодаря макросам ему можно простить такие косяки.


Что понравилось:


  • классы, объекты — всё это практически имеет нулевой оверхэд
  • сборка мусора работает довольно быстро
  • такой извращённой (в хорошем смысле) системы шаблонов и макросов я нигде не встречал
  • сборка через трансляцию в С, всегда можно его потюнить до производительности, сравнимой с C. К тому же можно распространять исходники в виде, оттранслированном в C — обфускация кода из коробки с неплохой переносимостью
  • хорош для разбора всевозможных xml/json и прочих разношёрстных конфигов с целью генерации отчётов
  • сравнительно безопасен, отстрелить ногу можно, но примерно с той же вероятностью, что и в питоне — по незнанию особенностей языка
  • легко подцепить функцию/библиотеку из C, если чего-то не хватает
  • очень легко собирается и самодостаточен, в плане переносимости лучшего варианта не сыскать
  • оптимизирующие шаблоны — отдельная песня. Можно целые куски кода, вроде "разделить строку по пробелам, взять подстроку длиной 10 символов от первого элемента" по мере необходимости переписывать на более оптимальные, с меньшей нагрузкой на сборщик мусора, при этом читаемость кода никак не пострадает. Эти шаблоны прячутся где-нибудь и ждут подходящего паттерна.

Что не понравилось:


  • баги — проклятье данного проекта. Их уже более 700, количество растёт, сообщество не успевает их фиксить.
  • удручающие решения в стандартной библиотеке. Ещё недавно чтение файлов работало посимвольно, через fgetc. Потоки (streams) — до сих пор небуферизованные, работают посимвольно и не спеша.
  • печальное состояние поддержки юникода и вообще какой-либо работы с языками, отличными от английского, отдельного упоминания достойна полная отсутствия поддержки переводов (по типу gettext)
  • биндинги к библиотекам сделаны на коленке любителями (см. GTK)
  • его пилит полтора человека, и ситуация не спешит меняться
  • регулярки прикручены наспех и работают медленнее, чем perl в десятки раз. Редкий язык, где реализация "в лоб" быстрее regexp.
  • отсутствует возможность использования рантайма, чтобы бинарники не пухли. Всё компилируется статически
  • сомнительная реализация исключений через longjump
  • из-за сборщика мусора нетривиально на нём разрабатывать библиотеки и модули к другим программам — требуется обязательное выполнение NimMain где-нибудь
  • коллеги смотрят на вас как на ненормального

Несмотря на недостатки, хороший язык "для себя" и можно на нём переписать что-то, что раньше было написано на Баше или Питоне, где нужна скорость. Продакшн даже не пробуйте — где вы потом программиста на Nim искать будете?:)


P.S. Подписываюсь на эссе по Nim от автора. Crystal пробовал — осталось впечатление, что он ещё более сырой, чем Nim.

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity