LINUX.ORG.RU

Избранные сообщения shdown

Эффективная оптимизация. Что такое Cython.

Форум — Development

За последнюю неделю почему-то часто всплывал этот вопрос, поэтому распишу всё сразу в одном месте. Описывать буду на примере питона, но общие принципы применимы ко многим языкам. Итак.

Часть первая. Правила эффективной оптимизация

  1. Не думайте об оптимизации пока код не дописан. Вообще! Думайте, как написать код проще и понятнее. А про оптимизацию даже не вспоминайте, пока не запустите код. Когда код запустится, проверьте насколько быстро он отрабатывает. Если он достаточно быстр — задача решена, ничего делать не нужно. Точка. И только если код отрабатывает медленнее, чем требуют условия задачи — начинайте думать об оптимизации.
  2. Попробуйте JIT, например PyPy, если условия это позволяют (apt-get install pypy && pypy yourprogram.py). Когда не хватает совсем немного производительности — JIT ускорит в несколько раз, и этого может быть достаточно. И тогда всё, задача решена. Только если это не сработало, переходите к фактической оптимизации кода.
  3. Пройдитесь профайлером. python -m cProfile yourprogram.py Никогда не оптимизируйте код без профилирования. По профилю определите самые медленные куски кода. Если код слишком большой — разбейте на функции. Не нужно бросаться переписывать всё подряд. Изолируйте наиболее прожорливые куски кода, и работайте только с ними.
  4. Выполните высокоуровневую оптимизацию найденных медленных кусков кода. Используйте более быстрые библиотеки: gmpy2 вместо встроенной длинной арифметики, python-regex вместо встроенного re, numpy для матричных вычислений, и т.д. Замените dict на list. Вынесите все возможные вычисления за циклы. Наконец, оптимизируйте алгоритм, или попробуйте найти ему более быстрый аналог. Если что-то получилось — goto 2.
  5. Cython. Расставьте типы, пройдитесь профайлером, посмотрите annotate cython-а, какой код сгенерирован, какие куски можно ускорить (он их расцвечивает)... Ещё раз подчёркиваю, низкоуровневая оптимизация — это последний этап, когда другие варианты исчерпаны.

Часть вторая. Cython

Если мы всё-таки дошли до cython-а, то... что же он такое?

Cython - это транслятор из питона в Си. Всё. Он просто генерирует код на си.

Если в файле mymodule.py написать:

def somefunc(x):
    y = x*42
    return y
и запустить cython mymodule.py то он том же каталоге сгенерирует mymodule.c, в котором будет что-то вроде:
static PyObject *__pyx_pf_8mymodule_somefunc(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_x) {
  PyObject *__pyx_v_y = NULL, *__pyx_r = NULL, *__pyx_t_1 = NULL;

  __pyx_t_1 = PyNumber_Multiply(__pyx_v_x, __pyx_int_42);
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_y = __pyx_t_1;
  __pyx_t_1 = 0;

  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_y);
  __pyx_r = __pyx_v_y;

  __Pyx_XDECREF(__pyx_v_y);
  __Pyx_XGIVEREF(__pyx_r);
  return __pyx_r;
}
И, хотя это редко делают вручную, этот код можно собрать обычным компилятором: gcc -shared -O3 -o mymodule.so mymodule.c `python-config --cflags --ldflags`. Нигде в остальном коде ничего менять не надо. Обычный «import mymodule» загрузит бинарный module.so так же, как загрузил бы питоновый mymodule.py.

Да, cython позволяет скомпилировать питонокод. Но никаких глубоких интеллектуальных оптимизаций cython не делает. Он просто вызывает из libpython.so питоновые функции, такие как PyNumber_Multiply(). Без питона этот код работать не будет. (в принципе, его можно собрать статически, но обычно это не имеет смысла — реальная программа всё равно будет использовать кучу внешних либ, и ещё одна библиотека роли не сыграет)

Так как все вызовы питоновых функций остались, то просто сборка cython-ом большого ускорения не даст, может, раза в два. Но! Cython-у можно указать, где использовать сишные типы вместо питоновых! В примере выше, если расставить типы:

cdef double somefunc(double x):
    cdef double y = x*42
    return y
то cython mymodule.pyx сгенерирует в mymodule.c код:
static double __pyx_f_8mymodule_somefunc(double __pyx_v_x) {
  double __pyx_v_y, __pyx_r;

  __pyx_v_y = (__pyx_v_x * 42.0);

  __pyx_r = __pyx_v_y;

  return __pyx_r;
}
По сути, это чистый код на си. Быстрее некуда. А с параметром --annotate cython -a mymodule.pyx дополнительно сгенерирует «mymodule.html», в котором раскрасит код цветами. По нему легко смотреть, какие части кода ещё стоит оптимизировать. Но так как после расстановки типов обычным питоном такой код уже не запустится, его традиционно сохраняют в файле с расширением .pyx вместо .py.

Вот так, не написав ни одной строчки на си, а просто расставив типы, медленный питоновый код превращается в быстрый сишный.

В целом, это всё.

PS: Это не все возможности cython-а. В нём можно использовать плюсовые типы, например std::vector. Причём можно даже писать: cdef vector[double] sqrs = [x*x for x in somelist] и всё преобразование из питоновых типов в плюсовые и обратно cython возмёт на себя. Можно вызывать и внешний код на си (cdef extern from).

Есть и более тонкие оптимизации, например мелким функциям можно расставлять inline (хотя с этим и gcc обычно справляется). А ещё код, не использующий питоновые объекты, не блокирует GIL! А значит отлично подходит для многопоточных вычислений. В cython-е есть и модули для параллельных вычислений.

Да и сами .pyx файлы обычно компилируются не руками, а как часть скрипта distutils/setuptool. А в отладочных целях import pyximport; pyximport.install() и после этого обычный import mymodule сможет импортировать не только .py, но и .pyx файлы.

Полезные ссылки

Итого: Оптимизировать надо только когда иначе нельзя, и только то, что необходимо. Низкоуровневая оптимизация делается в последнюю очередь. Но если мы её таки делаем, то cython позволяет сделать её максимально легко — просто расставив типы.

PPS: Питон в этом не уникален. Почти во всех языки есть возможности низкоуровневой оптимизации, расширения на си через FFI/JNI/и т.д. Есть unsafe код в rust и c#. Даже в паскале и си есть ассемблерные вставки. Не удивительно, что кто-то придумал аналог и для питона. Так что эти же принципы оптимизации применимы и к другим языкам.

 , , , ,

pynonymous ()

Поиск работы за границей РФ: доступ из вашей страны запрещен и другие важные вещи

Форум — Job

Как вы знаете, в РФ есть довольно странное законодательство на счет персональных данных, в котором зарубежные рекрутеры не хотят разбираться. Со стороны это выглядит так, как будто вы пошли на сайт например Red Hat или IBM, а нажать кнопку «apply» вам не дали, вывесив текст о том, что законодательство вашей cтраны не позволяет обрабатывать персданные за границей.

ВАЖНО: эту заглушку не ставит работодатель, ее ставит рекрутер потому что так ему посоветовал МакКинзи или Прайс, которые так посоветовали потому что увидели некоторый риск для рекрутера. Никаких других прчин для этого нет, если вы зайдете на ту же страницу с IP любой европейской страны или США, то ваше резюме будет принято, рассмотрено, вам будут звонить на ваш российский номер телефона.

Важно понимать, что перетащить вас из страны в страну стоит некоторого количества сил и денег. Самостоятельно этого добиться трудно, для этого есть специальные агенства, у которых есть отработанные процедуры. Из этого есть 2 важных прямых следствия и одно косвеное: искать работу стоит в больших корпорациях/стартапах с деньгами, которым не горит вас нанять и для которых затраты на перевозку не критичны. Просто составьте таблицу больших фирм, чья продукция вам нравится, сходите на их раздел «Карьера» и попроситесь на все-все вакансии, которые вам подходят. Второе следствие: естественно все эти затраты кратно вернутся работодателю за первые ваши 2 года работы, так как бизнес - деятельность по извлечению прибыли и единственная причина вас нанять и тащить через пол мира - маржинальность вашей деятельности (местный попросит больше денег и не будет так держаться за место как вы за визу). Это нормально, считайте их затраты на ваше беспроблемное перемещение своей косвенной прибылью. Самостоятельно вы все равно потратите больше, можете потерпеть неудачу не зная точно важных формальностей. Косвенное следствие: с идущими работать в большую корпорацию посольство обращается значительно мягче, чем с идущими работать в новую или мутную фирму.

Прежде чем посылать CV в большую фирму, сходите на Linkedin/Facebook, пройдитесь там по знакомым и укажите их как референсы в резюме. Вы не поверите, сколько пользователей ЛОР, например, в Бренском Red Hat или IBM и с каким удовольствием они оставят о вас отзыв своему HR. Cпойлер: это возможные премии во многих конторах, так что не стесняйтесь спрашивать и просить рекомендации.

UPDATE из 2019. Теперь по крайней мере Red Hat заставляет формально аппаиться через российское представительство посте того, как зааплаился через VPN.

Перемещено Falcon-peregrinus из job

Перемещено Klymedy из talks

 , ,

Shaman007 ()

Научите utf8 в perl

Форум — Development

Использую perl 5.20 в debian 8. Вот такой код:

#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use open qw(:utf8 :std);
use Data::Dumper;

print "тест utf8\n";
my @files = glob "Стільниця/*";
push @files, "кирилица для Dumper";
print Dumper @files;

2/0; # Делаем ошибку для проверки utf8 в STDERR

Даёт вот такой результат:
Useless use of division (/) in void context at ./Стільниця/test_utf8.pm line 14.
тест utf8
$VAR1 = 'Стільниця/тест.txt';
$VAR2 = 'Стільниця/test_utf8.pm';
$VAR3 = "\x{43a}\x{438}\x{440}\x{438}\x{43b}\x{438}\x{446}\x{430} \x{434}\x{43b}\x{44f} Dumper";
Illegal division by zero at ./Стільниця/test_utf8.pm line 14.

Как видите нормально прошло только print с строкой utf8, всё остальное ..., ну вы видите. Как заставить perl выводить кирилицу а не кракозябры???
А ещё где-то читал что в perl самая лучшая поддержка юникода. Если это называется «лучшая» то мне страшно представить что творится в других языках.

 

SyntaxError ()

Валидатор IP-адресов

Форум — Development

Наваял софтину для проверки правильности написания IP-адресов (IPv4 и IPv6) на Си. Ничего сложного и оригинального, возможно, велосипед с квадратными колёсами, но это я в качестве тренировки, чисто для себя, так как на C пишу мало.

Цель написания — получить отзывы, поэтому с удовольствием жду обоснованную критику, лучше с патчами.

Если кому интересно, то исходники тут.

 , , ,

post-factum ()

Haskell, монады, память, и все-все-все

Форум — Development

Есть задача - пройтись по текстовому файлу и найти максимальное число одинаковых последовательно идущих строчек. Задача весьма синтетическая, просто надо продемонстрировать, что

  • Потоково обрабатывается некий объем данных;
  • Есть состояние - надо помнить предыдущую строку в файле при обращении к следующей.

Решение в лоб на IORef-ах (m1.hs):

module Main where

import Data.IORef
import Control.Monad (forM)

main :: IO ()
main = do
   input    <- getContents
   lastLine <- newIORef (Nothing)
   counter  <- newIORef (0)
   result   <- newIORef (0)

   let incr    = modifyIORef counter (\x -> x `seq` x+1)
       reset s = do c <- readIORef counter
                    r <- readIORef result
                    writeIORef result (max c r)
                    writeIORef lastLine (Just s)
                    writeIORef counter  1

   forM (lines input) $ \line -> do
     ml <- readIORef lastLine
     case ml of
       (Just s) -> if s == line then incr else reset line
       Nothing  -> reset line

   r <- readIORef result
   putStrLn $ "Largest subsequence of equal lines: " ++ show r

Более модное решение с трансформером StateT (m2.hs):

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Main where

import Control.Monad (forM)
import Control.Monad.State.Strict

data AppContext = AppContext { ctxLastLine :: Maybe String
                             , ctxCounter  :: Integer
                             , ctxResult   :: Integer
                             }

initialContext :: AppContext
initialContext = AppContext { ctxLastLine = Nothing
                            , ctxCounter  = 0
                            , ctxResult   = 0
                            }

newtype App a = App (StateT AppContext IO a)
                deriving (Monad, MonadIO, MonadState AppContext)

runApp (App app) = execStateT app

incr :: App ()
incr = do
   cnt <- gets ctxCounter
   modify $ \s -> s { ctxCounter = cnt+1 }

reset :: String -> App ()
reset l = do
   cnt <- gets ctxCounter
   res <- gets ctxResult
   modify $ \s -> s { ctxLastLine = Just l
                    , ctxCounter  = 1
                    , ctxResult   = max res cnt
                    }

processLine :: String -> App ()
processLine line = do
   ll <- gets ctxLastLine
   case ll of
      (Just s) -> if line == s then incr else reset line
      Nothing  -> reset line

main :: IO ()
main = do
   input <- getContents
   s <- runApp (forM (lines input) processLine) initialContext
   putStrLn $ "Largest subsequence of equal lines: " ++ show (ctxResult s)

Интересно, как поведут себя оба варианта на обработке, скажем, «Улисс» Джойса (txt, 1.6 MB):

[dmatveev@localhost memq]$ ghc --make m1.hs -rtsopts -prof
[1 of 1] Compiling Main             ( m1.hs, m1.o )
Linking m1 ...
[dmatveev@localhost memq]$ ghc --make m2.hs -rtsopts -prof
[1 of 1] Compiling Main             ( m2.hs, m2.o )
Linking m2 ...
[dmatveev@localhost memq]$ du -sh ulysses.txt
1.6M    ulysses.txt
[dmatveev@localhost memq]$ wc -l ulysses.txt
33055 ulysses.txt
[dmatveev@localhost memq]$ time cat ulysses.txt | ./m1 +RTS -hd -i0.001
Largest subsequence of equal lines: 5

real    0m1.599s
user    0m1.577s
sys     0m0.021s
[dmatveev@localhost memq]$ time cat ulysses.txt | ./m2 +RTS -hd -i0.001
Largest subsequence of equal lines: 5

real    0m19.360s
user    0m19.123s
sys     0m0.091s

ШОК! Посмотрим, что там с памятью:

[dmatveev@localhost memq]$ hp2ps -e8in -c m1.hp
[dmatveev@localhost memq]$ hp2ps -e8in -c m2.hp

m1.png, m2.png

Очевидно, что во втором примере что-то течёт, а я что-то глобально упустил.

Вопросы:

  1. ЧЯДНТ?
  2. Как быть?
  3. Как правильно готовить монадические ивентлупы с изменяемым состоянием?

З.Ы. Да, я знаю, что на awk это решается проще и быстрее, суть-то не в этом, а в вопросе №3. Извините за неровный почерк.

 ,

yoghurt ()

А вы уже обновили свой libpng? :)

Форум — Development

В своих проприетарных и/или статически слинкованных поделиях, в сборках под макось и винду? :)

А вот в линуксах обновил юзверь одной командой пакетного менеджера libpng и всё, нету больше уязвимости, мэйнтейнер дистра за вас постарался

 , , , ,

Harald ()

В чем глубинный смысл ttyACMx?

Форум — General

Сабж. Прочитал несколько статей на тему разницы ttyUSBx и ttyACMx.

Как я понял, ttyUSBx это UART, подключенный на usb. А ttyACMx это нечто, прикидывающееся модемом, и вовсе необязательно ведущее себя как uart.

Т.е. вроде как tty* != uart. Или не так? зачем это сделано? Кому сейчас нужны реальные терминалы, чтобы ради них городить tty? причем так, что uart кроме как через tty недоступен. И к тому же не всякий tty это uart.

Например, в QNX, емнип, нет /dev/ttyS0, а есть /dev/ser1, который именно uart, без всяких tty заморочек.

Да, насколько я помню, tty* можно использовать так, чтобы он ничего не вставлял лишнего, а сразу гнал данные в порт. Но зачем вообще тащить это наследие времен, когда компьютеры были большими?

Перемещено mono из talks

cvs-255 ()

Запретить шрифт в X11

Форум — Desktop

Пакетируют шрифты часто скопом, и получается, что два пакета тянут похожие гарнитуры, а мне бы хотелось и держать шрифты пакетами в системе, и при этом сделать список доступных шрифтов почище. Конкретно хотелось бы запретить гарнитуру Nimbus в urw-fonts, ибо такая гельветика не нужна. Можно, конечно, перепаковывать, но это как-то оверкилл.

 , ,

deterenkelt ()

dbus выносит мозг

Форум — Talks

...Одному из мэнтейнеров Gentoo, Patrick Lauer-у. Он удосужился прочитать документацию по dbus и офигел от её кривости. Потом он решил посмотреть на код, и тут ему полностью снесло крышу. После чего он основательно напился и решил написать разгромную статью, где проводит подробный разбор опусов авторов dbus. В заключение он говорит (для Ъ):

Хоть я и узнал много нового, мне кажется невероятным, что это недокументированное поделие кто-то может серьезно использовать. Многие концепции либо не определены, либо определены через реализацию. Все API сделаны как попало без какой-либо структуры, часто встречаются дупликаты (какая разница между Terminate и Kill?), а независимая реализация не представляется возможной. Если это будущее, то лучше я останусь в прошлом...

 , , ,

rupert ()

Вы все еще думаете, что FF не скатился, а CTR — панацея?

Форум — Talks

Тогда поставьте это дело на экран, с DPI большим, чем обычное.

И выставьте layout.css.devPixelsPerPx соответственно.

Наслаждайтесь.

Для Ъ: в CTR рамки вкладок — картинки. Мастштабирование соответствующее.

Ну а обсралис просто говен.

 , , ,

derlafff ()

Посоветуйте гетеросексуальный почтовый сервис

Форум — Talks

Сабж. Требования: pop3/smtp/imap, плюсом будет возможность приделать собственный домен. Размер ящика значения не играет, т.к. за 8 лет на lavabit до его кончины я так и не смог заполнить стандартные 128мб.

Сразу скажу, gmail, yandex, mail.ru, outlook и прочие выкидыши прогресса не предлагать: уже натерпелся геморроя с ними. GMX вроде неплох, но у них регистрация уже хрен знает который день не работает - по ссылке sign up вылетает страница с надписью «The requested Page wasn't found».

UPD: спасибо user42, сделал ящик на fastmail.com

 

hateyoufeel ()

Наконец-то запилили нормальный Alt-Tab

Форум — Desktop

xwinmosaic, cyclefocus, особенно первый - полезные и годные реализации, но как-то, лично я, не был удовлетворен и в душе всегда не терял надежды, что запилят нормальный Alt-Tab.

И это наконец-то свершилось: http://i.imgur.com/t3910Xg.png

Недавно появилось, небоян:

там можно кастомизировать, нормальный запилить себе дезигн.

 ,

vim ()

SMPlayer не проигрывает некоторые файлы

Форум — Desktop

Не может открыть некоторые файлы форматов mp4, aac, может еще каких - выдает ошибку - код 1.

/usr/bin/mplayer -noquiet -nofs -nomouseinput -sub-fuzziness 2 -identify -slave -vo xv, -ao pulse -nokeepaspect -framedrop -nodr -double -input nodefault-bindings:conf=/dev/null -stop-xscreensaver -wid 65011751 -monitorpixelaspect 1 -noass -subfont-autoscale 1 -subfont-text-scale 5 -subcp enca:ru:UTF-8 -subpos 100 -volume 100 -cache 2048 -ss 186 -osdlevel 0 -vf-add screenshot -noslices -channels 2 -af scaletempo,equalizer=0:0:0:0:0:0:0:0:0:0 -softvol -softvol-max 110 /home/votafak/Музыка/Sirenia - At Sixes And Sevens (full album , 2001).aac

MPlayer2 2.0-701-gd4c5b7f-2ubuntu2 (C) 2000-2012 MPlayer Team
Terminal type `unknown' is not defined.

Playing /home/votafak/Музыка/Sirenia - At Sixes And Sevens (full album , 2001).aac.
Cache size set to 2048 KiB

Cache fill:  0.00% (0 bytes)   

Detected file format: QuickTime / MOV (libavformat)


MPlayer interrupted by signal 11 in module: demux_open
ID_SIGNAL=11
- MPlayer crashed by bad usage of CPU/FPU/RAM.
  Recompile MPlayer with --enable-debug and make a 'gdb' backtrace and
  disassembly. Details in DOCS/HTML/en/bugreports_what.html#bugreports_crash.
- MPlayer crashed. This shouldn't happen.
  It can be a bug in the MPlayer code _or_ in your drivers _or_ in your
  gcc version. If you think it's MPlayer's fault, please read
  DOCS/HTML/en/bugreports.html and follow the instructions there. We can't and
  won't help unless you provide this information when reporting a possible bug.

а в htop'е остается процесс

/usr/bin/mplayer -noquiet -nofs -nomouseinput -sub-fuzziness 2 -identify -slave -vo xv, -ao pulse -nokeepaspect -framedrop -nodr -double -input nodefault-bindings:conf=/dev/null -stop-xscreensaver -wid 65011751 -monitorpixelaspect 1 -noass -subfont-autoscale 1 -subfont-text-scale 5 -subcp enca:ru:UTF-8 -subpos 100 -volume 100 -cache 2048 -ss 186 -osdlevel 0 -vf-add screenshot -noslices -channels 2 -af scaletempo,equalizer=0:0:0:0:0:0:0:0:0:0 -softvol -softvol-max 110 /home/votafak/Музыка/Sirenia - At Sixes And Sevens (full album , 2001).aac

Была версия SMPlayer 0.8.6, я ее удалил, установил с сайта версию 14.9.0 - проблема осталась. Что делать?

 

votafak ()

Terminal, shell и tty (ptty) в Linux

Форум — General

Здравствуйте, правда очень стыдно спрашивать такие вещи. Дело в том, что уже намного сложнее вещи изучил в архитектуре и работе самой ОС. А вот тут стал чувствовать, что есть провал в понимании и знаниях. Решил спросить, чтобы окончательно разобраться. Проблема вот в чем. Раньше вроде пользовался терминалом и все нормально. А теперь начал углубленно разбирать строение и архитектуру linux подобных систем и возникло непонимание происходящего. Читал кучу статей, но к сожалению не нашел того что надо. 1. Терминал, консоль (shell). Насколько я понимаю это единственный способ сделать системный вызов. То есть только с помощью него происходит взаимодействие с ядром операционной системы ? Чем данный исполняемый файл отличается от других, что может иметь доступ к системным вызовам. Знаю что у каждого пользователя прописан свой интерпретаторв passwd.Можно ли было без терминала обойтись ? 2. Что такое tty. Читал про последовательные порты, историю, один компьютер и много пользователей. Что общего между tty & shell(terminal). Зачем сделана возможность при нажатии на Ctrl+Alt+FX получать доступ к этому устройству. И какую роль он вообще играет в системе. 3. Как устроено все это в встроенных линуксоподобных системах как Android. На вики написано, что там обычно нету The Linux console is an optional kernel feature, and most embedded Linux systems do not enable it.

То есть у меня тотальное непонимание взаимодействия терминала, псевдотерминала с ядром и в общем в системе. Пожалуйста, не пишите фразы типа : «Что ты тут вообще делаешь, иди учи матчасть, как можно работать в линукс не зная такого.....». И сам знаю. Объясните пожалуйста, что и зачем надо, просто хочу разобраться в этом. Или дайте что источники где это описано для таких как я. Спасибо всем заранее.

 , , , ,

CROSP ()

Виджет mpd для Awesome - выдает только N/A - N/A

Форум — Desktop

Слушаю музыку с mpd. В качестве гуйни к нему - Cantata.
Понадобился осомовиджет для этого. Использовал пример из вики к vicious.widgets.mpd.
Код виджета:

    mpdwidget = wibox.widget.textbox()
    vicious.register(mpdwidget, vicious.widgets.mpd,
    function (mpdwidget, args)
        if args["{state}"] == "Stop" then 
            return " Not Playing "
        else 
            return args["{Artist}"]..' - '.. args["{Title}"]
        end
    end, 10)
Конфиг mpd, предоставленный Cantata:
music_directory "/home/princess-cadance/music-lossless/"
playlist_directory "/home/princess-cadance/.local/share/cantata/mpd/playlists"
sticker_file "/home/princess-cadance/.local/share/cantata/mpd/sticker.sql"
bind_to_address "/home/princess-cadance/.local/share/cantata/mpd/socket"
db_file "/home/princess-cadance/.cache/cantata/mpd/tag_cache"
pid_file "/home/princess-cadance/.cache/cantata/mpd/pid"
state_file "/home/princess-cadance/.cache/cantata/mpd/state"
log_file "/dev/null"
metadata_to_use	"artist,album,title,track,name,genre,date,disc,albumartist,composer"
audio_output { 
  type "alsa"
  name "Output"
}
mixer_type "software"
audio_buffer_size "8192"
filesystem_charset "UTF-8"
id3v1_encoding "UTF-8"
Виджет всегда выдает только N/A - N/A. Почему так? awesome --version:
awesome v3.5.5 (Kansas City Shuffle)
 • Build: Aug 25 2014 20:55:55 for i686 by gcc version 4.7.3 (@Gentoo-TD)
 • Compiled against Lua 5.1.5 (running with Lua 5.1)
 • D-Bus support: ✔
mpd --version:
Music Player Daemon 0.18.14

 , ,

DeadEye ()

Ман по Firefox + userChrome.css

Форум — General

Хотел я попилить Firefox с помощью файла из сабжа. Не могу нагуглить справочник по элементам UI Firefox. Если такой есть, дайте, пожалуйста, ссылку. Если же нет, подскажите, пжлст, чем можно взглянуть эти элементы UI и их код с CSS самому.

 , , , ,

DeadEye ()