Archive for the ‘Кодерство’ Category
Корисні налаштування Git
Перше. Як не задовбувати всіх сміттям яке створює ваше IDE, і за замовчуванням мати gitignore для всіх репозиторіїв.
git config --global core.excludesfile ~/.gitignore
Ця команда відредагує файл ~/.gitconfig
і в ~/.gitignore
можна буде перелічити всякі там *.swp
, чи що там ваш редактор створює.
Друге. Якщо Go не хоче встановлювати модулі з помилкою “fatal: could not read Username for ‘https://github.com’: terminal prompts disabled”, бо залежності прописані через https, а ви використовєуте SSH, це можна виправити таким налаштуванням:
git config --global url."git@github.com:".insteadOf "https://github.com/"
На цьому поки що все, дякую за увагу. 🙂
Скільки слів треба щоб написати вікіпедію? І які зустрічаються частіше?
Виявляється відтоді як я рахував символи вікіпедії пройшло вже більше року. Рахував я їх за допомогою Go, хоча можна було сильно спростити собі життя і рахувати їх за допомогою Python і pywikipediabot. Сьогодні розкажу як, і як можна побачити з назви – рахуватимемо слова.
Я чомусь боявся що щоб порахувати слова пам’яті не вистачить, тому треба якусь базу даних. Або пробувати все в пам’яті, але аби комп’ютеру не стало погано якось обмежити доступну пам’ять. Але мої 4Gb використовувались лише щось трохи більше ніж на 40% для підрахунку всіх слів включно зі сторінками обговорень, категорій, шаблонів, сторінок опису файлів, і т.п. німецької вікіпедії.
В модулі pywikibot.pagegenerators
є об’єкти XMLDumpOldPageGenerator
і XMLDumpPageGenerator
. Вони приймають назву архіву з XML дампом в конструкторі, а після створення по них можна ітеруватися отримуючи об’єкти сторінки. Не ведіться на слово “Old” в назві першого об’єкта, це означає не депрекацію, а те що текст сторінки буде братись з дампа, а в другому випадку з дампа буде братись лише заголовки, а за свіжим текстом зроблять запит, що сповільнить обробку разів в 500. Тобто замість кількох годин ви будете чекати рік. 🙂
Я спробував проаналізувати німецьку вікіпедію (код буде пізніше), на це пішло 694 хв (трохи менше ніж 12 годин) і вийшло що в ній на 6,425,028 сторінках використовується 2,381,457,397 слів (приблизно 371 на сторінку), з них різних слів 18,349,393. В кінцевому результаті CSV з частотним словничком виходить на 300MB.
Серед тих що зустрічаються лише раз є слова типу PikettdienstPikettdienst (помилка парсера який видаляв розмітку), слово – це юридичний термін швейцарської німецької і перекладається як “служба за викликом”. І є слова на зразок Werkshöfe – подвір’я фабрик.
Топ 50 слів виглядає так, і складає 28% всіх слів загалом:
der | 58761447 | sich | 9169933 |
und | 49084873 | wurde | 9114619 |
die | 44536463 | CET | 8614461 |
in | 35684744 | an | 8385637 |
von | 24448221 | er | 7835324 |
ist | 20614114 | dass | 7550955 |
den | 19454023 | du | 7435099 |
nicht | 17519638 | bei | 7420172 |
das | 17302844 | Diskussion | 7237855 |
zu | 16167971 | aus | 7065523 |
mit | 15906145 | Artikel | 6967243 |
im | 15167140 | oder | 6824420 |
des | 14661593 | werden | 6508092 |
für | 14016308 | war | 6449858 |
auf | 13957013 | nach | 6426826 |
auch | 12849476 | wird | 6117566 |
eine | 11903977 | aber | 6052645 |
ein | 11780352 | am | 6017703 |
Kategorie | 11369651 | sind | 5953632 |
als | 11167157 | Der | 5623930 |
dem | 11124726 | Das | 5545595 |
CEST | 11104741 | einen | 5465687 |
ich | 10886406 | noch | 5409154 |
Die | 10761776 | wie | 5293658 |
es | 10204681 | einer | 5228368 |
До списку потрапили такі вікіпедійно специфічні слова як Kategorie (сторінки без категорій вважаються не комільфо), CEST і CET (центральноєвропейський літній час і центральноєвропейський час, в підписах в обговореннях).
Ну а що без сторінок обговорень? Проблемав тому, що при створенні об’єкту сторінки XMLDumpOldPageGenerator
бере з дампа лише текст і заголовок, простір імен залишається не заповненим і за замовчуванням 0 (основний). Є ще поле isredirect
так при спробі доступу до нього знову здійснюється запит. Тому, краще перейти на рівень нижче і використати XmlDump
з pywikibot.xmlreader
, він використовується так само, просто дає об’єкти не Page, а попростіші, які не вміють робити запити до вікіпедії і не мають методу save
. Але нам його й не треба, правда?
Ось код який ігнорує перенаправлення і всі сторінки крім статтей:
"""Count word frequencies in wikipedia dump""" import csv from collections import Counter from itertools import islice import re import sys import mwparserfromhell from pywikibot.xmlreader import XmlDump def main(): """Iterate over pages and count words""" if len(sys.argv) < 2: print('Please give file name of dump') return filename = sys.argv[1] pages = 0 words = 0 words_counts = Counter() print('Processing dump') for page in XmlDump(filename).parse(): if (page.ns != '0') or page.isredirect: continue try: text = mwparserfromhell.parse(page.text).strip_code() except Exception as e: print(page.title, e) continue text = text.replace('\u0301', '') # remove accents # Ukrainian: # page_words = re.findall( # r'[абвгґдеєжзиіїйклмнопрстуфхцчшщьюя' # r'АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ’\'-]+', # text # ) # Any language: page_words = re.findall(r'\b[^\W\d]+\b', text) pages += 1 words += len(page_words) words_counts.update(page_words) if pages % 123 == 0: print('\rPages: %d. Words: %d. Unique: %d. Processing: %s' % ( pages, words, len(words_counts), (page.title + ' ' * 70)[:70], ), end='') print('Done. Writing csv') with open('common_words.csv', 'w', newline='') as csvfile: csvwriter = csv.writer(csvfile) for item in words_counts.most_common(): csvwriter.writerow(item) if __name__ == '__main__': main()
Він працює майже вдвічі швидше, 381 хвилину, бо обробляє лише 2,295,426 сторінок (обсяг німецької вікіпедії цього року). На цих сторінках є 1,074,446,116 слів (в середньому 468 на сторінку), з них різних – 12,002,417. (Виявляється є аж 6 мільйонів всяких слів які вживаються на всіляких службових сторінках німецької вікіпедії, і яких нема в статтях).
Якщо ж взяти українські статті, то на них треба ще менше часу – 131 хвилину (забув уточнити що в мене SSD), їх є 923238 (скоро мільйон!), слів 238263126 (в середньому 258 на сторінку, треба доповнювати 😉 ). З них різних – 4,571,418. Отак, в мене тепер є частотний словник української на 4.5 мільйони слів. І німецької на 12 мільйонів.
Хоча не спішіть з висновками що українська мова бідніша, бо мої методи потребують вдосконалення. По перше, так як Morgen (ранок) і morgen (завтра) – різні слова, то я не приводив букви в німецькій до одного регістру. (Правда й в українській забув це зробити).
По друге, в німецькому словнику 350590 разів зустрічається слово “www”, бо я вважав словом будь-яку послідовність літер латинки, а в українській відфільтрував кирилицю. Слово youtube зустрічається 8375 разів, а значить є ризик знайти якесь рідкісне слово на зразок “fCn8zs912OE”. 🙂
На WordPress глючить додавання картинок, тому нате вам відео:
А, і ось топ-10 української вікіпедії:
в,4551982
на,3730686
і,3475086
у,3353796
з,3053407
-,2695783
Категорія,2417267
та,2350573
до,1815429
року,1553492
Частота “року” наводить на думку що в українській вікіпедії якийсь перекос на історичні методи викладу. 🙂
Kubernetes з microk8s
Kubernetes – це такий docker-compose на стероїдах, що дозволяє керувати кластером машин на яких запускаються контейнери. Infrastructure as a code, і всяке таке. Дивно що в цьому кібернетичному блозі про кібернетіс ще жодного разу не згадувалось, тому варто цю ситуацію виправити.
Інсталяція
Є різні способи поставити локально однонодовий кластер, minikube (з яким в мене не дуже вийшло), і microk8s, який на Ubuntu, і лінукси в яких є менеджер пакетів Snappy, ставиться так:
sudo snap install microk8s --classic
Це встановить кластер і CLI для керування кластером kubectl
. Правда вона називатиметься microk8s.kubectl
. Якщо ви не ставили kubectl
окремо (можна через той же snap install
) для керування кластером десь в хмарах, то можна зробити аліас, а якщо ставили – так можна переконфігурити її для роботи з локальним кластером:
microk8s.kubectl config view --raw > ~/.kube/config
Тоді можна наприклад отримати список нодів кластера:
$ kubectl get nodes NAME STATUS ROLES AGE VERSION bunyk-latitude-e5470 Ready <none> 3h v1.14.0
Логічно що у випадку локальної інсталяції це буде лише один комп’ютер.
Щоб перемкнути kubectl
на керування наприклад якимось кластером в хмарах Google, за умови що у вас встановлений gcloud
, треба виконати:
gcloud container clusters get-credentials [CLUSTER_NAME]
Аддони й панель керування
Ще microk8s
має команди для вмикання (enable
) і вимикання (disable
) аддонів:
microk8s.enable dns dashboard
dns потрібний для багатьох речей, тому його радять вмикати. dashboard – web UI, і InfluxDB з Grafana для моніторингу ресурсів. Щоб його побачити, треба викликати kubectl proxy
і перейти за адресою: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login
Там попросять залогінитись, щоб отримати JWT токен для логіну, треба виконати
kubectl -n kube-system get secret # тоді в списку знайти ім'я що починається з kubernetes-dashboard-token- # а тоді: kubectl -n kube-system describe secret kubernetes-dashboard-token-c4bmp
Параметр -n означає простір імен, це щось на зразок директорії де лежать всі об’єкти кластера, наприклад секрети. Це також відображається в шляхах до API, як от /api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
для доступу до сервісу https:kubernetes-dashboard. За замовчуванням kubectl
працює з простором імен default
, але у випадку вище, нам треба kube-system
.
Запуск контейнерів в Kubernetes
Тепер може спробуємо щось запустити? Для цього треба створити под (pod – англійське слово що позначає групу китів. Вони взагалі дивні слова мають для цього. Зграя сов – це parliament, круків – murder). Под – це група контейнерів зі спільною IP адресою, які запускаються а ноді.
Найпростіший спосіб створити под – майже такий самий як запустити контейнер:
kubectl run nginx --image=nginx # kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead. # deployment.apps/nginx created
Це говорить нам що команда створила deployment, але в майбутньому створюватиме лише поди, якщо не передати параметр --generator=run-pod/v1
. Чому так пояснюють тут.
Що таке деплоймент? Нуууу, це важко пояснити, і це мене найбільше в Кубернетісі вибішує. Под – це набір конейнерів зі спільною IP адресою, набором портів, диском, і т.д. Под сам по собі запускати в kubernetes не рекомендують, бо після того як в нього трапиться якась аварія наприклад через закінчення пам’яті, його ніхто не перезапустить. Подом керує контролер, одним з яких є контролер що називається ReplicaSet, який задає кількість копій пода що мають бути запущені. І якщо одна з них з якихось причин здихає – запускається нова, щоб кількість завжди відповідала потрібній. Deployment – об’єкт що містить контролер ReplicaSet, і керує версіями імеджів контейнерів в подах цього контролера. Абстракцій як в TCP/IP…
Тим не менш, ми побачимо под в списку:
$ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-7db9fccd9b-w6468 1/1 Running 1 44h
Щоб видалити деплоймент разом з подами дають команду:
kubectl delete deployments/nginx
Трохи складніший спосіб створити под – написати маніфест:
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx name: nginx ports: - containerPort: 80 name: http protocol: TCP
Якщо його записати в файл, наприклад nginx.yaml
, то щоб запустити:
kubectl apply -f nginx.yaml
Як подивитись що всередині пода? Можна прокинути порт, і тоді те що контейнери в поді віддають на якомусь порті буде доступно на порті localhost:
kubectl port-forward nginx 8088:80
Загальне правило для портів в Kubernetes (бо такі пари порт:порт зустрічаються часто) – зліва порти ззовні, справа – всередині. Якщо все працює, на http://localhost:8088 ви маєте побачити сторінку де пише “If you see this page, the nginx web server is successfully installed and working.”
Можна подивитись логи:
$ kubectl logs -f nginx 127.0.0.1 - - [31/Mar/2019:17:00:53 +0000] "GET /favicon.ico HTTP/1.1" 404 154 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-" 127.0.0.1 - - [31/Mar/2019:17:01:56 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0" "-"
Як змінити те що под показує на головній? Створити якийсь html файл і закинути його командою:
kubectl cp index.html nginx:/usr/share/nginx/html/index.html
Хоча так не прийнято робити, і можна хіба що під час розробки. Краще додати файли в імедж за допомогою Dockerfile.
Запуск сайту
Але давайте вже зробимо щось серйозне на кілька контейнерів. Наприклад як в цій публікації було за допомогою docker compose, тільки за допомогою kubernetes: два контейнери, один з них nginx веб-сервер що віддає статичні файли для фронт-енду, інший – API на python що віддає дані графіків.
Таким чином файли backend.docker
, dashboard.html
і server.py
можна скопіювати собі в проект без змін (звідси). nginx.docker
напевне краще називати frontend.docker
, і помістити туди лише файли фронт-енду:
FROM nginx COPY dashboard.html /usr/share/nginx/html/index.html
Конфігурацію nginx ми змінювати не будемо, бо відповідальним за диспетчеризацію запитів між фронт-ендом і бекендом в нас буде штука що називається Ingress.
Тут, на відміну від docker-compose
який сам наші контейнери може зібрати, їх треба створити вручну:
docker build -t frontend -f frontend.docker . docker build -t backend -f backend.docker .
Покладемо конфіг для двох деплойментів у файл site.yaml
і скажемо кластеру оновитись (kubectl apply -f site.yaml
):
apiVersion: apps/v1 kind: Deployment metadata: name: frontend-deployment spec: selector: matchLabels: tier: frontend replicas: 1 template: metadata: labels: tier: frontend spec: containers: - name: frontend image: frontend ports: - containerPort: 80 --- apiVersion: apps/v1 kind: Deployment metadata: name: backend-deployment spec: selector: matchLabels: tier: backend replicas: 2 # більше подів для бекенду, бо йому самому може важко. template: metadata: labels: tier: backend spec: containers: - name: backend image: backend ports: - containerPort: 80
Один файл в Kubernetes може містити описи багатьох об’єктів, розділені рядком що містить “—“. Так простіше працювати, бо треба менше команд kubectl apply
, чи kubectl delete
.
Якщо kubectl get pods
показує що наші поди мають статус ErrImagePull
або ImagePullBackOff
, це означає що kubernetes намагається взяти імеджі не з нашого комп’ютера, а з докерхабу.
Виявляється треба ще додати їх в реєстр microk8s. Для цього:
microk8s.enable registry docker tag backend localhost:32000/backend docker push localhost:32000/backend docker tag frontend localhost:32000/frontend docker push localhost:32000/frontend
Підозрюю що це можна було зробити простіше і швидше якщо зразу називати імеджі правильним тегом. Але майстерність приходить з досвідом. 🙂 В кінцевому результаті ви маєте мати три запущені поди, в двох деплойментах.
І що з того? Поки нічого, бо IP адреси цих подів динамічно міняються (коли їх перезапускають). Для того щоб мати постійний доступ потрібен сервіс, який проксює доступ до подів заданих мітками (labels). Мітки це пари ключ-значення які чіпляються до об’єктів в Kubernetes. Коли ми в описі пода писали:
labels: tier: backend
То це ми йому якраз задавали мітки. Тепер по мітках ми можемо ці об’єкти отримувати:
bunyk@bunyk-thinkpad:~/projects/dockerizing$ kubectl get pods -l tier=frontend NAME READY STATUS RESTARTS AGE frontend-deployment-695cfcc94c-jl5hg 1/1 Running 0 3h6m bunyk@bunyk-thinkpad:~/projects/dockerizing$ kubectl get pods -l tier=backend NAME READY STATUS RESTARTS AGE backend-deployment-669d885465-cfbrc 1/1 Running 0 3h6m backend-deployment-669d885465-nh8lg 1/1 Running 0 3h6m
Так само сервіс має надає доступ з постійним IP до набору подів заданого мітками. Сервіси створюються так:
apiVersion: v1 kind: Service metadata: name: backend spec: selector: tier: backend ports: - protocol: TCP port: 80 targetPort: 8080 --- apiVersion: v1 kind: Service metadata: name: frontend spec: selector: tier: frontend ports: - protocol: TCP port: 80 targetPort: 80
Сервіс має селектор що визначає за якими подами стежити, і відкриває порти. port
– це який порт відкрити, targetPort
– це до якого порта в поді приєднатись. За цим треба слідкувати, бо якщо не виконається одна з умов: порт на якому слухає сервер в контейнері == containerPort, containerPort == targetPort сервіса, port сервіса == порт до якого приєднується клієнт, то отримаємо помилку “Connection refused” чи подібну.
Після чергового kubectl apply -f site.yaml
можна подивитись які сервіси отримуємо:
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE backend ClusterIP 10.152.183.69 <none> 80/TCP 110m frontend ClusterIP 10.152.183.63 <none> 80/TCP 30m kubernetes ClusterIP 10.152.183.1 <none> 443/TCP 8d $ curl 10.152.183.69/data/1 [1.0997977838,0.6222197737,0.7265324166,1.0475918458,0.8271129655,0.6489646475,0.3625859258,0.7692987393,1.1331619921,1.4889188394]
Бачимо що сервіси які ми створюємо мають тип ClusterIP. Це тип за замовчуванням, і означає що він буде доступний лише з середини кластера. Нам доступний, бо ми ж сидимо на одній єдиній ноді кластера. Крім нього є ще NodePort
, LoadBalancer
і ExternalName
, але розбиратись що це – ми не будемо, бо й без того голова вже пухне (чи у вас ні?).
Залишився ще Ingress. Це штука що дає доступ до сервісів кластера ззовні кластера. Конфігурується так:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: entrypoint annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 kubernetes.io/ingress.class: "nginx" spec: rules: - http: paths: - path: /api/(.*) backend: serviceName: backend servicePort: 80 - path: /(.*) backend: serviceName: frontend servicePort: 80
Перед тим як її створювати, треба ще виконати microk8s.enable ingress
.
Тут важливий параметр nginx.ingress.kubernetes.io/rewrite-target
, який означає “передавати сервісу запит замінивши URL на той що вказано, підставивши групи з регулярного виразу в path
“.
Після застосування цієї конфігурації, на localhost в нас завантажиться фронтенд, пошле через ingress запити до бекенду, і все навіть буде через HTTP 2.0.
Питайтесь якщо що не виходить чи не доходить, в мене теж багато з того що тут написано не виходило зразу, може я вже стикався з тими проблемами що у вас.
Хакери викрали базу даних пін-кодів!
Важлива інформація для власників банківських карток Visa і MasterCard, поділіться з друзями і знайомими щоб вони теж були попереджені.
Нижче викладаю копію бази даних з вкраденими пін-кодами. Перевірте чи ваш є серед них, і якщо є – рекомендую змінити на якийсь інший, якого нема серед списку зламаних.
Прочитати решту цього запису »
Docker і обмеження ресурсів
Раніше я вже писав собі шпаргалку по докеру, яка нікому крім мене майже не потрібна, тут буде додаток до неї.
Контейнери докера – це аналог процесів в ОС – тобто щось що запущено виконується. Запускаються імеджі (аналог виконуваної програми). Можна взяти готовий імедж, можна зробити свій за допомогою докерфайла (аналог коду програми), який описує як білдиться (аналог компіляції) імедж.
Загалом команда запуску контейнера виглядає так:
docker run $image_name [$command]
Наприклад якщо цікаво виконати якийсь код на останньому Python, але лінь його ставити, докер скачає і виконає:
docker run python:latest python -c "import sys; print(sys.version)" # Unable to find image 'python:latest' locally # latest: Pulling from library/python # 22dbe790f715: Pull complete # ... # 61b3f1392c29: Pull complete # Digest: sha256:c32b1a9fb8a0dc212c33ef1d492231c513fa326b4dae6dae7534491c857af88a # Status: Downloaded newer image for python:latest # 3.7.2 (default, Mar 5 2019, 06:22:51) # [GCC 6.3.0 20170516]
Якщо не передавати ніяку команду, контейнер виконуватиме ту що для нього задана за замовчуванням. Наприклад
docker run --name test_python_run python:latest # задаємо контейнеру ім'я щоб не сплутати з іншими: docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d95e1e13e3f2 python:latest "python3" 5 seconds ago Exited (0) 4 seconds ago test_python_run
Бачимо що контейнер запускав команду “python3” але вийшов з неї (бо термінал не приєднався). Щоб увійти в інтерактивну сесію, треба запускати так (-i вроді означає інтерактивно, тобто очікувати на stdin, -t – приєднати до поточного терміналу):
docker run -it python:latest
Тільки через командний рядок багато Python коду не передаш. Тому є два варіанти передати файли в контейнер. Перший – прямо в image, за допомогою dockerfile.
Візьмемо для експерименту такий скрипт що поступово пробує використати все більше й більше пам’яті:
import random import time data = [] for i in range(10 ** 6): data.append(random.random()) if i % 1000 == 0: print(len(data)) time.sleep(0.25)
Managing memory in Python is easy—if you just don’t care. Документація Theano.
Щоб створити з ним імедж достатньо такого докерфайлу:
FROM python:3.7 COPY script.py ./script.py CMD python script.py
Тепер, щоб створити з нього імедж який називається наприклад memeater
(зжирач пам’яті), треба виконати:
docker build -t memeater -f Dockerfile .
А щоб потім запустити цей контейнер:
docker run -t memeater
-t щоб бачити що він пише в stdout.
Далі ми можемо за допомогою команди docker stat
спостерігати за тим скільки ресурсів цей контейнер їсть:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 8a58c19cc93c exp 0.28% 6.02MiB / 10MiB 60.20% 3.17kB / 0B 565kB / 1.01MB 2
Аби він не з’їв всю доступну пам’ять, можна йому обмежити ресурси:
docker run -t --name experiment --memory="10M" --cpus=0.1 memeater
Якщо вискакує повідомлення “WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.”, значить у вас трохи не такий Linux, і обмеження стосуватиметься лише RAM, а не області підкачки. Задати параметр --memory-swap
теж не допоможе.
Допоможе – взагалі відключити зберігання сторінок на диск.
docker run -t --name experiment --memory="20M" --memory-swappiness=0 --cpus=0.1 memeater
Якщо отримуєте помилку “docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused “process_linux.go:424: container init caused \”\””: unknown.”, то це тому що обмеження по пам’яті за сильне. В мене при 10M вискакує, при 20 – ні.
Що відбувається коли пам’ять закінчується? Лог закінчується так:
492001 Killed
З цього експерименту можна зробити висновок що Python, запущений в системі з доступною пам’яттю 20 мегабайт може втримати в пам’яті трохи менше ніж пів мільйона чисел з плаваючою крапкою.
Кілька рядків коду що підвищують продуктивність в рази
«Не потоком шумних і галасливих фраз, а тихою, невтомною працею любіть Україну!»
Це клікбейтний заголовок, але тут ми дійсно за пару хвилин напишемо розширення до браузера, щось на зразок resquetime тільки просте як одноклітинні. Назвемо його наприклад higher power
, бо воно працюватиме як підстраховка для нашої власної сили волі.
Створюємо директорію проекту
bunyk@bunyk-thinkpad:~/projects$ mkdir higher_power bunyk@bunyk-thinkpad:~/projects$ cd higher_power/
А в ній файл manifest.json
з наступним вмістом:
{ "manifest_version": 2, "name": "Higher power", "version": "1.0", "description": "Helps you to avoid temptations", "icons": { }, "content_scripts": [ { "matches": ["*://*.facebook.com/*"], "js": ["power.js"], "run_at": "document_start" } ] }
Версії і назва – обов’язкові поля, опис та icons – ні, але корисні, бо відображатиметься в списку додатків, а content_scripts
описує який код завантажуавти при відкриванні певної адреси.
“run_at” каже запускати код ще до того як сторінка завантажиться, без цієї опції браузер пару секунд рендерить стрічку фейсбука, а тоді вже наш аддон починає щось робити.
Створимо цей код, в згаданому в маніфесті файлі power.js
, нариклад так:
window.location.href="https://bunyk.wordpress.com/";
Замість bunyk.wordpress.com можна вписати https://www.udacity.com/, https://www.edx.org/, https://github.com/ чи щось таке.
Тепер відкриваємо в Firefox сторінку “about:debugging” (для інших браузерів самі з’ясуйте що і напишіть в коментарі будь ласка), натискаємо кнопку “Load Temporary Add-on…”, вибираємо будь-який файл з директорії нашого проекту, і насолоджуємось результатом.
Посилання
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension
Рукотворна штучна нейронна мережа
Коли приходить зима часом хочеться щоб домашня машина для перетворення електричної енергії в теплову (так директор ФТЛ називає комп’ютери) працювала на всіх парах. Але крім того хочеться аби вона робила щось цікавіше за обчислення хеш функцій якогось блоку криптовалюти. Часом залишаю комп’ютер на ніч попрацювати над вікіпедією, але це задача скоріше зав’язана на швидкість мережі і диска, тому процесор майже не завантажує.
Публікація про те що прості штучні нейронні мережі не такі вже й складні. Алгоритм їх навчання я ще не ґрокнув але навчився складати їх вручну задаючи топологію і всі коефіцієнти, тому така нібито тавтологічна назва. Насправді нейронні мережі не складаються вручну, а самонавчаються різними методами, бо для типових задач штучного інтелекту вони занадто великі аби це було можливо. Але все одно вони залишаються просто купкою матриць, тільки великих.
Прочитати решту цього запису »