サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
災害への備え
qiita.com/methane
Python 3.3 から __init__.py を省略して良いと思っている人が多いですが、 省略しないでください。 なぜ勘違いが起こったのか Python 3.3 から、 PEP 420 で Implicit namespace package が追加されました。 Namespace package とは普通の package ではありません。 特殊な用途のもので、ほとんどの人にとっては 知る必要すらない ものです。 どうしても知りたければ、上の PEP 420 と packaging guide を読んでください。 __init__.py を省略する弊害 普通の package で Implicit namespace package を乱用すると弊害があります。 import が遅くなる 通常の package とは違うので import が package 内のモジュールを探すの
どんなに軽いクエリでも、たとえばWebサーバーとMySQLの間のRTTが5msあって20クエリを実行したらRTTだけで100msかかってしまいます。 たくさんのデータをinsertするときは bulk insert (VALUES の後に複数の行を書くクエリ) を使うテクニックは有名です。しかしこのテクニックは次のような場合に使えません。 複数のテーブルに1行ずつINSERTしたい 複数のUPDATEやSELECTをまとめたい たとえば弊社のある案件で次のような場面がありました。 新規ユーザー作成時に大量のテーブルにINSERTしたい ログイン時に大量のテーブルにSELECTしたい こういった場面を高速化するために multiple statements と multiple result sets を利用しました。 Multiple Statements 複数のクエリを ; で区切って一
Python をビルドするとき、 configure で --enable-optimizations を指定するとビルド時に PGO (Profile Guided Optimization) を利用することができます。 PGO を有効にすると、一度ビルドしたバイナリを実行してプロファイルを取得し、そのプロファイルデータを利用してもう一度最適化ビルドをします。このプロファイル取得のために Python のテストを実行していたのですが、普通のPCでは20分以上かかる上に並列実行することもできませんでした。 --enable-optimizations を指定したときにプロファイル取得に使われるテストを 419 モジュールから 40 モジュールに減らす改善が 取り込まれました。 なので Python 3.8b3 からはPGOを利用したビルドが速くなります。 ちなみに、 --with-lto
Microsoft の mimalloc は面白い割り切り方で、小さいソースコードで高速なアロケータを実装しています。 確保するメモリブロックのサイズを、 Small (~8KiB), Large (~512KiB), Huge (512KiB~) の3つに分類し、 Small と Large は同じアルゴリズムで管理し、 Huge は OS 任せにして、 Small と Large は同じアルゴリズムをうまく利用しています。 基礎 OSはpage (x86では基本 4KiB) ごとにメモリをプロセスに割り当てています。 しかしアプリケーションではずっと小さいメモリブロックが必要になることが多くあります。また、必要になるたびに毎回OSからメモリを割り当ててもらうのはパフォーマンスも悪いです。 mimalloc やその他の malloc 実装 (以降 malloc と呼びます) は OS か
Microsoft が microsoft/mimalloc という新しいアロケータを公開しました。 https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action/ によると、 One increasing use-case for allocators is as back-end implementations of languages, such as Swift and Python, that use reference counting to automatically deallocate objects. We present mimalloc, a memory allocator that effectively balances these dema
Python 3.8 に導入1した LOAD_GLOBAL 命令用の per-opcode cache について紹介します。 LOAD_GLOBAL 命令 Python のグローバル変数のロードはローカル変数のロードに比べて遅いです。そのためにグローバル変数に繰り返しアクセスする場合は一旦ローカル変数に格納するというテクニックがあったりします。 $ python3 -m timeit -s ' > def foo(): > for _ in range(1000): > sum > ' -- 'foo()' 10000 loops, best of 5: 29.9 usec per loop $ python3 -m timeit -s ' def foo(): _sum = sum for i in range(1000): _sum ' -- 'foo()' 20000 loops,
TL;DR: UTF-8をデフォルトで使いたい人は環境変数に PYTHONUTF8=1 を設定しよう Python は文字列が unicode なので、あちこちで「適切」なエンコーディングを選択する必要があります。残念ながら後方互換性やWindows固有の事情によりまだ ANSI Code Page (日本語なら cp932) がデフォルトで使われる場面があります。 ざっと Python と外の世界との入出力をあげてみます。 テキストファイルを読み書きする時のデフォルトのエンコーディング = ACP 標準入出力のエンコーディング 標準入出力がコンソールのとき = UTF-16 で WriteConsoleW 等を呼ぶ 標準入出力がコンソールでない時 = ACP 子プロセスとのPIPE = ACP 最近 chcp 65001 を使って UTF-8 を使う方法が広まっているように思います。これ
はじめに zstd コマンド(zstdless, zstdcat, unzstd なども)は gzip にも対応しています。特にデコードは拡張子を見て自動で gzip と zstd を切り替えてくれるので、 gzip 圧縮されたログと zstd 圧縮されたログが混在している環境でも透過的に扱うことができます。 なので gzip から zstd への切り替えは次のように段階的に進めることができます。 zstd コマンドツール群のインストール 圧縮されたログを扱うときに zstd を使い始める 圧縮フォーマットを zstd に切り替える 性能比較 Debian 9.3 で gzip 1.6 (aptでインストールしたもの) と zstd (1.4.0) を比べてみます。 対象となるファイルは ltsv でゴチャゴチャとアプリの情報を混ぜた重めの apache のアクセスログです。 (5,367
http.ListenAndServe() を使ったサーバーをプロダクションに投入していたのですが、海外からのアクセスが多くなったころにリソースリークが発覚しました。 ListenAndServeのドキュメント ListenAndServeのソースを見るとこうなっています。 func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe() } addr, handler 以外は http.Server のnil値がそのまま使われている事がわかります。この構造体にはいくつかのタイムアウト値がありまが、nil値で初期化されるとタイムアウトなしの状態になってしまいます。 Server型のドキ
Python 3.7 では {} で作った空 dict よりも、 dict.clear() で作った空 dict の方が省メモリでした。 >>> import sys >>> d = {} >>> sys.getsizeof(d) 240 >>> d.clear() >>> sys.getsizeof(d) 72 これは dict オブジェクトを新規作成するときに最小サイズのハッシュテーブルを確保し初期化するのに対して、 dict.clear() は shared key dict の仕組みを使って空 dict 専用の共有テーブル(書き込み禁止)を利用しているからです。 空の dict の数は無視できないくらいにはあるので、Python 3.8 で新規に dict オブジェクトを作るときも dict.clear() の結果と同じ共有領域を使うようにしました。 なお Python 3.7 の
Python はデフォルトで多くの警告を表示しません。これはPython開発者ではないエンドユーザーが警告を見た時に混乱するのを防ぐためです。 デフォルトで ignore される Warning は次のとおりです。 (ref: https://docs.python.org/3/library/warnings.html#default-warning-filters) DeprecationWarning PendingDeprecationWarning ImportWarning BytesWarning ResourceWarning これらの warning を Python 開発者が表示しないと、せっかく使っているライブラリが長期間 Deprecation 期間を設けていてもその Warning に気づかないとかいう事が起きます。 また、 warning システムは同じ場所から
Pythonプロジェクトのディレクトリ構成 という記事を見かけたのですが、どうも constraints の使い方について誤解が広まっているようです。 この記事で利用されている requirements.txt と constraints.txt の正しい実現方法と、 constraints の本来の使い方を紹介しておきます。 バージョンロックの実現方法 プロジェクトで Flask を使うとしましょう。特にバージョンに関して意見が無いので requirements.txt はこの状態で始めます。 $ pip install -r requirements.txt $ pip install flask Collecting flask Downloading Flask-0.12.2-py2.py3-none-any.whl (83kB) 100% |███████████████████
ISUCON7 の本戦では、更新処理の直後に、その更新操作を反映したデータを返さないといけない、しかもそのデータの計算がとても重いという問題を出題しました。 もともと ISUCON では「POSTが200を返したら、それ以降のGETリクエストにはその結果が反映されてなければいけない」というルールが課されることが多いのですが、今回の問題もそのバリエーションの一つといえます。 さて、今年になって singleflight を知り、この種の課題にも使えそうだと思っていました。 (参考 golang.org/x/sync/singleflightで重複呼び出しを排除する) そこで今年の問題を事前に Go でチューニングして見るときに試してみたのですが、普通に適用しただけでは整合性が取れずに失敗してしまいました。そこで調べた singleflight の注意点とワークアラウンドを紹介しておきます。
EC2 の c5 インスタンスタイプが発表されました。 参考: https://dev.classmethod.jp/cloud/aws/ec2-c5-instance/ 個人的に今までのGCEやEC2の不満は PMU が使えないことです。例えば perf コマンドでキャッシュミスや分岐ミスをプロファイリングできません。 C5インスタンスではハイパーバイザーがKVMに変更されたということで、この点に変化が無いか調べてみました。結果、 9xlarge (1ソケット専有) と 18xlarge (ホスト=2ソケット専有) では Hardware PMU Event を見ることができました。(テナンシーは通常の「共有」のまま、AMI は Amazon Linux 2017.9) 結果: https://gist.github.com/methane/3c523b7bc8e99508a90ca06
Rubyist が pyenv を使うときに知っておいてほしいこと で、 「pyenv を Python をビルドするためだけに利用する方法」について紹介しました。 そこで「シェルを軽量化し、 shims も利用しないようにする事ができます。」と書いたのですが、具体的にコマンドを shims 経由で起動するオーバーヘッドについて紹介しておきます。 $ type python3 python3 は /Users/inada-n/pyenv/shims/python3 です $ pyenv shell 3.6.1 $ python3 -VV Python 3.6.1 (default, May 18 2017, 16:23:51) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] $ time python3 -S -c 42
はじめに 機械学習ブームなどにより、 Python を触り始める Rubyist が増えてきたと思います。その際に問題になりやすいのが環境構築です。Rubyだと rbenv がデファクトスタンダードになっているのに、なぜか Python には pyenv に否定的な意見が多いんですよね。 私は pyenv を使っていますし、便利だと思っています。また、 Ruby は殆ど使わないのですが、RubyとPythonのツールスタックの違いについても調べました。 (参考: gem, bundler と pip, venv の比較) その視点から、 Rubyユーザーが自分でpyenvの使い方を自分で決める上で知っておいた方が良いだろうなと思う Ruby と Python の環境の違いをまとめてみます。 tl;dr 丁寧に解説しても、「Python使うにはこんな長い記事を読まないといけないの」とすぐに否
はじめに 非同期プログラミングと呼んでいるのは、ノンブロッキングIOと select, poll, epoll, kqueue のようなIO多重化を利用したネットワークアプリケーションを書くことです。 node.js で websocket 使ったチャットを書くとかそういうのです。 「他の多くの言語」とは、 Python (asyncio), node.js, C# などを想定しています。 Erlang や GHC なんかは Go に近いかも知れません。 async / await がない言語では、「コールバック地獄」や「deferred地獄」のような問題もありますがこの記事では扱っていません。 async / await のメリットを解説した他の記事を参照してください。 あとこの記事は主にランタイムに関する部分を扱っているので、「それは言語じゃなくて処理系の問題だ!」等の頓珍漢な揚げ足取
(この記事は Dave Cheney さんの Why Go? の翻訳です。) 数週間前、友人に「Goに注目に値するのはなんで?」と聞かれました。 彼は私がGoに情熱を注いでいることを知っていましたが、なぜ私が他の人もGoを気にするべきだと思っているのかを知りたいようでした。 この記事は、私がGoを重要なプログラミング言語だと考える、3つの大きな理由を紹介します。 メモリ安全 個人としては、私もあなたもC言語でメモリリークも危険なメモリの再利用もしないプログラムを書く事ができるでしょう。しかし、40年以上の経験から、集団としてのプログラマーはC言語で信頼できるプログラムを書けない事がはっきりしています。 コードの静的解析、 valgrind, tsan (訳注: たぶん ThreadSanitizer), -Werror といったツールは10年以上前から使えますが、それらのツールが広く認知さ
普段は mac で ja_JP.UTF-8 を使ってるけど、 Linux では予想しない挙動の変化が起きるのを嫌って C locale を使う人、いますよね。僕も常にではないけれど結構 C locale 好きです。 でも、 C locale を使うと、 vim が (set encoding=utf-8 を書いていないと) デフォルトで latin1 になって文字化けしまくったり、 Python が (export PYTHONIOENCODING=utf-8 しておかないと) 標準入出力がasciiになって UnicodeError になったりしてツラい気持ちになることもあります。 そんなときは、 LANG=C, LC_CTYPE=en_US.UTF-8 で LC_ALL は設定しないようにするのがただしい locale の設定方法なんですが、最近のモダンな Linux に搭載されてる
Python 2 に比べるとずっと楽になったものの、環境によっては Python 3 で予期せぬ UnicodeError に遭遇することがあります。 Python 3.6 時点での、 Python の各種エンコーディングの扱いを整理してみます。 Python のエンコーディング filesystem encoding (sys.getfilesystemencoding()) 主にファイルパスに使うエンコーディングですが、コマンドライン引数にも使われます。 (そうでないとファイルパスをコマンドライン引数に渡したときに困る) また locale が関連するので、実際にはそれ以外にも glibc とかと連携するときに使われます。 Python 2 時代の名残りでしょうが、今では filesystem encoding というより system encoding と呼んだほうが実態を表している
x と y は別々に作られた、別々のリストオブジェクトです。なので、 x is y は False になりますし、 x を変更しても y には影響しません。 一方、 z は x と同一のオブジェクトを参照しています。なので x is z は True になりますし、 x (が参照しているリストオブジェクト)を変更すると当然 z も同じように変化します。 整数型は immutable オブジェクトが示す値が、オブジェクトを生成したときに決まり、その後変化しないようなオブジェクトを immutable といいます。 整数は immutable です。次のサンプルコードを見てください。 y = x した直後は、 x と y は同じ 42 を表すオブジェクトを示しているので x is y は True でした。 x += 1 すると、 x には 43 を表す別のオブジェクトが代入されます。なので
この記事は個人ブログで海外向けに書きかけの記事の日本語版です。そのため、一部日本人向けではない記述が含まれます。 英語版はこちらです Why you must not ask questions on Github issues 現在は GitHub は Discussions を提供しています。 Issue Template から Discussion へと誘導するのがおすすめです。 2023-06-14 追記 TL;DR: Issue Tracker で質問するのは開発者に対する DoS 攻撃になるかもしれない。 Forum がある場合は Issue Tracker で質問してはいけない。 背景 Github の時代になる前は、ある程度の規模のOSSプロジェクトはみんな Issue Tracker と別に フォーラム (BBS, ML など) を持っていました。ユーザーはフォーラムでデ
Ruby や Python でできたツールの README には、よくインストール方法として gem install redcarpet とか pip install pygments どとシンプルなコマンドが書かれています。 ですが、このインストール方法をみたときに、Rubyに慣れてない人は「どうせ gem install してもなんかよくわからないエラーがでて、愚痴ったら bundler 使わないほうが悪いみたいに言われるんだろ」とか、Pythonに慣れてない人は「これどこにインストールするの? bundler みたいなのないの?」と思うかもしれません。 少なくとも私は gem install でインストールするツールを敬遠していました。でも、「これだから gem は…」と愚痴るのは違うだろう、 Rubyist は pip install に同じ思いを持ってるだろうと思ったので、私のよ
Rubyのリファクタリングでイケてないコードを美しいオブジェクト指向設計のコードへ改良するための方法 - その1 その2 その3 これを Python でやってみます 元のコード 元の Ruby 版をできるだけ真似してみます。テストは py.test を使います。 #ordersreport.py from collections import namedtuple Order = namedtuple("Order", "amount placed_at") class OrdersReport: def __init__(self, orders, start_date, end_date): self.orders = orders self.start_date = start_date self.end_date = end_date def total_sales_within
TL;DR 負荷の変動が激しい環境でコネクションプールの設定のチューニングをさぼるためによくやるハックを紹介します。 問題 Go から https や mysql など外部のリソースにアクセスする場合、一般的にコネクションプールを使うことになります。 コネクションプールは、利用が終わった (idle) コネクションをプールしておき、次に使いたい時に再利用するものです。 (idle コネクションのプールを以後 free pool と呼びます。) ほとんどのコネクションプールの実装には、 idle なコネクションの最大数を制限するオプションがあります。 また、利用中の (active) コネクションと idle なコネクションを合計した全体を制限するオプションを持つものもあります。 例えば net/http パッケージの Transport は MaxIdleConnsPerHost というフ
この記事は Let’s talk about logging の翻訳です。 Nate Finch による Go Forum への投稿で始まったスレッド を見てこの記事を書くことにしました。 この記事は Go を対象にしていますが、あなたのいままでのやり方を振り返ってみたら、同じ考え方がより広く適用できると思います。 なんでこんなに足りないの? 訳注: "Why no Love?" を、「(愛されてないから)機能が足りない」というニュアンスで解釈しましたが、自信が無いです。 Go の log パッケージ はレベル付きのロギングを提供していません。なので手動で debug, info, warn, error のようなプレフィックスを書く必要があります。 また、 Go はパッケージごとにログの出力レベルを制御する方法も提供していません。 比較対象としてサードパーティーのロギングライブラリを見て
expvar パッケージは手軽にメトリクスを公開するのに使えて便利なのですが、複数の値を公開するための例があまり公開されてなくて分かりにくかったので書いておきます。 expvar.Map を使う mychat というチャットアプリを作ってると仮定して、送受信メッセージ数と、同時接続数を公開してみます。 /debug/vars を見た時に、次のような形でメトリクスを公開します。 ... mychat: { "conns": 42, "msg_recv": 10480, "msg_sent": 88946 }, ... package metrics import ( "expvar" ) var ( Map = expvar.NewMap("mychat") // expvar.NewXxx() は直接公開するメトリクスを作成する。 Conns = new(expvar.Int) // Ma
ベンチマークや重いソフトウェアのビルドなど、ノートPCには適していない作業をするマシンとして、いままで AWS のスポットインスタンスを使っていました。 しかし5月に GCE のプリエンプティブインスタンスが出て、試してみたところ予想以上に快適でした。 こういったスポットでの作業環境としてのプリエンプティブインスタンスのメリットを紹介していきます。 起動が早い スポットインスタンスは、入札してから実際にマシンが起動するまでのタイムラグが5分程度ありました。 プリエンプティブインスタンスは、通常の Compute Engine のインスタンスのオプションという扱いなので、入札という手順が存在せず、1分程度で起動できます。 設定が簡単 AWS だと新しいインスタンスを使おうとすると VPC の設定が必要だったり、セキュリティグループの設定をしないと起動した2台のマシン間での通信すらできなかった
[uwsgi] ... processes=10 cheaper-algo=spare2 cheaper=2 cheaper-initial=2 cheaper-step=2 cheaper-idle=30 process=10 は最大ワーカープロセス数です。 cheaper=2 が最小プロセス数になり、この間で調整されることになります。 cheaper-initial=2 が起動直後のワーカー数になります。 spare2 アルゴリズムは、 cheaper で指定された数の idle 状態のワーカー数を維持しようとします。 例えば idle 状態のワーカー数が 1 つになった場合、 2 - 1 = 1 個のワーカーを起動します。 cheaper-step=2 は一度に起動するプロセス数の上限です。 cheaper が大きいときに、 cheaper-step であまりたくさんのプロセスを一気
次のページ
このページを最初にブックマークしてみませんか?
『@methaneのマイページ - Qiita』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く