自作の青空文庫リーダーの動作は大変重く、昔のPC、例えばPentiumM1GHzとかだと実用限度ぎりぎりです。
少しでもレスポンスをよくしようといろいろ試行錯誤していますが、CPythonは所詮バイトマシンであり、その処理速度には限界があります。俗にCの10倍遅い等といいますが、納得の遅さ。

で、高速化へのアプローチとして部分的にCに書き換えるという方策があります。この手の小細工は大昔、MS-DOSの上でミックスドランゲージプログラミング(俺がやったのはQuickBASICとMASM、あるいはTurboCとTASM)に明け暮れた身としては懐かしさもありますが、その煩わしさたるや相当なものがあってできれば避けたいもの。

幸い21世紀の今日(こんにち)、マシンパワーは向上し処理系もオープンソースでいろいろ試すことができるいい時代です。今回はCythonというものを試してみることにしました。

これはPythonをCに変換するトランスレータの一種で、専用の予約語を追加することで多少なりとも生成コードを制御する、というもののようです。
ネットで漁った情報によれば、単純に変換した場合はおよそ倍の速度、Pythonにおけるオーバーヘッドの原因たるレイトバインディングを回避するよう調整を施すと、ものによっては100倍まで速度が向上するそうです。

使い方
1)まず、Cythonの処理系をインストール。OSは例によってPuppyLinux571JP。リポジトリにもありますが、バージョンが少し旧かったのでCythonのサイトからソースをダウンロードして自前でインストールしました。
圧縮ファイルを展開後、python setup.py install でインストール。普通にgccを呼んでいるようで環境変数CFLAGSを見ます。

2)変換しようとするPythonソースファイル(以下、hoge.py)のあるディレクトリに、次のsetup.py を設置。
#! /usr/bin/python
# -*- coding: utf-8 -*-

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [Extension('hoge', ['hoge.pyx'])]  
setup(
      name        = 'hoge app',
      cmdclass    = {'build_ext':build_ext},
      ext_modules = ext_modules
      )

3)hoge.pyをhoge.pyx にリネーム。
4)このディレクトリで python setup.py build_ext を実行。正常終了すると hoge.so ライブラリが生成されているので、
python setup.py install_lib でインストール。/usr/local/lib/python2.7/dist-packages に入る。
5)このモジュールを使う場合は import pyximport を実行しておく。

青空文庫リーダー内のフォーマッターと描画ルーチン部分をCythonにかけてみたところ、確かに速くなったような感じがします。が、それはわずかなものでした。

原因は、
  • Pygtkを始めとする既存のモジュールはCythonによる高速化の埒外にある。
  • 処理内容の性質上、文字列(Unicode型)の操作がほとんどで、単純にCに置換できない。
  • cdef による修飾がクラスメンバに対しては容易でなく、Pythonから大幅な書き換えを要する。(おそらく。深く検討してないので何か策があるのかも。)
  • pango関係で生じたメモリリークはCythonでも当然生じるため、根本的な解決のため描画部分をサブプロセスにせざるを得ず、この部分のオーバーヘッドは今回の方法ではほとんど改善が見込めない。

以前、JITコンパイラであるPyPyも試したことがありますが、それと比較すると、
Cython
長所
・とりあえず、CPython向けに用意されているライブラリ(GUIツールキット類も含む)のほとんどがそのまま使える。
・極端な向上は見込めないものの、確かに速くはなる。
・soライブラリとして出力されるので他の言語から呼び出せる。また、配布に際しては多少なりとも秘匿性が付与することができそう。
短所
・速度を稼ごうとしてソースコードを改変すると、どんどんPythonから離れて行って最終的には別言語のソースコードになってしまう。
・故の学習コストが生じる。
・インストール先でビルドできない場合はsoライブラリを配布することとなり、環境依存性が生じる。また、別途インストーラを用意しなくてはならない。

PyPy
長所
・コンスタントに数倍、うまくいけば8倍位の速度向上が見込める。
・CPythonと高い互換性がある。
短所
・CPython向けのライブラリ、特にGUIツールキット類が使えないことがある(最近はどうだか知らん)。

以上、Cythonのファーストインプレッションでした。ソースコード無改造での速度向上具合に難はあるものの、変換処理は簡単なので試す価値はあると思います。また、最初から「Cythonを通すことを前提にPythonで書く」といったことをすれば効率的なような気もします。

キーボードの設定方法
/opt/bootlocal.sh に
loadkmap < /usr/share/kmap/qwerty/jp106.kmap と書く。

RC版の際には全然問題なかったネットアクセスがまったくできない。LANは成立している。リポジトリのアドレスが違うのか?

MintをインストールしたPCはLenovo のThinkPadR500というもので、これにはbluetoothインターフェースが内蔵されている。

以前、PuppyLinuxで実験した際はずいぶん苦労した覚えがある。しかし手元のbluetooth機器は、旧式のAndroid端末、USBドングル、オーディオレシーバの3つしかなく、すぐに使うのを止めてしまった。端末や他のPCとのデータ交換ならLANで間に合うし、オーディオレシーバのほうは音量調整ができなかった。Androidを親として接続した場合は可能だったのでPC側の問題だったのだが、然程必要性も感じなかったので原因を深く追求することなく止めてしまった。

時は流れ(といっても2、3年位と思うが)Bluetoothそのものも一時ほど騒がれなくなった気がする。だからという訳でもないだろうが、LinuxMint 17.1はデフォルトでは使えないようになっている。

以下、オーディオレシーバが使えるようになるまで。
1)Bluemanをインストールする。
Synapticを使ってインストールした。必要なものは一通り入る模様。
2)鳴き合わせを行う。
これがなかなか一発で通らない。Puppyの時もそうだったし、オーディオレシーバそのものも長らく通電していなかったので調子が悪くなっている可能性がある。固定パスワードを使ったりとか試行錯誤の末何とか開通。
3)pulseaudioが認識しない
PuppyLinuxではpulseaudioを使ってこなかったので、ここで躓くとまったく予備知識無しで挑まなくてはならない。
ネットを漁ったところ、設定ファイルの一部書き換え、及びモジュールの手動ロードで解決した。
/etc/bluetooth/audio.conf
[Headset]
HFP=false
SBCSources=1
MPEG12Sources=0
なお、上記以外に
[General]
Disable=Socket
も要るらしいが、なくても大丈夫だった。
 
pactl load-module module-bluetooth-discover
都度手動というのは煩わしい。多分どこかに設定箇所があるはず、と思うが見つけていない。

4)音量調整を開いて、「再生」タブにてアプリケーションでの出力先を設定する。


前後するが、正しく認識されてしれば「出力装置」タブに出現する。

pulseaudioのおかげで音量調整が可能である。また、バッテリー切れでレシーバを切断した途端にPC本体のスピーカに切り替わる等、うまく動いている。

常用するならモジュールの読み込ませ方法等解決しなくてならないが、レシーバのバッテリーが弱っていて1時間位しかもたないので、今回もこのままで終わりそうな気がする。


 

OSの違いによる、青空文庫リーダーの表示の様子。

LinuxMint 17.1 (x64) Xfce



システム標準のSerifフォントのままだとうまく表示できなかったので、とりあえずTakaoEx明朝を指定。このため、JIS未収録文字は表示できない(はず)。見出しに使っているSansフォント(おそらく可変ピッチ)の大きさがTakaoEx明朝と互換性がないので、途中で折り返したように見える。


tahr pup CE 6.0 (SP6.0.2) + 日本語sfs1.9



同じUbuntu Trusty tahr由来なので同じ表示になるか、と思いきや不具合発生。Sansフォント(M+1P+IPAG)に縦書き向けが含まれていないから、からと思われる。SerifはTakaoEx明朝。





開発環境であるPrecise puppy 571JP,(Pango改変済み)における表示。

インストールされたフォント及びそれらのまとめ具合で状況は大きく変わる。とはいえ、Linux Mint 17.1における表示は開発環境と大差なかった。最近のPangoの挙動は改善されていると考えていいのかも知れない。


 

PyGtk を使って何か作るとき、メニューの構築には長らく関数というかメソッドを並べてきたのだが、今回初めてUIManagerを使ってみた。何で今まで使ってこなかったかといえば、資料が少ないことと何より使わなくても済んだ、ということに尽きる。

青空文庫リーダーでは履歴及び目次を動的に生成してメニューに表示している。このうち、目次については処理をUIの外部から行っているので問題ないが、履歴のほうはそうはいかなかった。

履歴を参照してテキストを読み込む一連の作業の間、実は履歴項目にアタッチされたアクションから離れていない。この状態で履歴の内容を書き換えようとすると、実行中のコードを破棄する格好になりそれでは困るのでエラーになる。

で、半ば諦めていたのだけれど、どんなアプリケーションでも何かファイルを開閉したら履歴にはすぐに反映されてUIから参照可能になっているから、自作のアプリケーションでそれができない、というのは実に格好がつかないのですね。

ということで、少ない資料(とはいえ、公式サイトのチュートリアルにはきちんと書かれているのだが)を参考にしつつ、書き改めました、1日掛かりで。定義しているにも関わらず、アクションが見つからなくてエラーになる謎挙動に悩んでいたのですが、何のことはない、名前の最初を大文字にしていてひっかかっていたのでした。

UIManager というだけあって、キーボードショートカットまで面倒を見てくれるのでキートラップルーチンが短くなったのは思わぬ収穫でした。メニュー定義部分も随分と簡潔になったし、メニューと同じ内容をポップアップメニューに流用したりするのも簡単で、どうして今まで使わなかったのか、と。
 

Tinycore 6 だけど、その後分かったことなど。勘違いしている部分もあるかもしれない。

キーボード配列の入れ替え
果たせず。触っているうちにUS配列に慣れてそれなりに打てるようにはなった。

日本語表示
適当なTTFをもらってきて (/usr/libの下の、だったかな?)X11/fonts/default/TTF に放り込み、fc-cache -f を実行したところ、firefox ではきちんと表示できるようになった。

ロケール問題
firefox を端末から起動させたところ、Cライブラリはロケールに対応していない、とのワーニングが出る。firefoxに言語パッケージをインストールして、端末にてexport LANG=ja_JP.UTF-8;firefox 等とやってもUIが日本語に切り替わらないのはこれが原因かも知れない。

ネット接続が切断される
システム起動後、firefox をロードし、wbarや仮想端末から起動するとネットアクセス可能になるのだが、一旦閉じてから再度使おうとすると接続できない。ルーターやADSLモデムへのピンは通るのでLANが遮断されている訳ではなさそう。

再起動すると設定が飛ぶ
ダウンロードしたtgz等はそのまま残っているので再度ロードすればよいが、手動でインストールしたフォント類は揮発していた(~/Downloadsに落としたファイルは無事)。そういう仕様なんだろう。PuppyLinuxのようにどこぞに保存しておいてくれると助かるのだが。必要であればリマスタしろ、ということか。

なかなか手強いなあ。仮想環境でも30秒で起動するし、全体のRAMを256MB設定にしてビデオドライバはvesaにも関わらずFirefoxはきびきび動いた。この軽さは確かに魅力だけれど、日本語環境を構築するまで相当かかりそうです。


 

x86向けのコンパクトなLinuxが欲しくてLFSなんぞに手を出してみたりしたのだけれど、結局面倒くさくなって中断している。世間一般では挫折したともいうけど。

小さい、という点ではPuppyLinuxも小さいとは思うが最近のバージョンはそれなりに大きい。で、思い出したのが TinyCore Linuxなのでありました。

目下、6.1rc2が最新版らしい。ISOをダウンロードして仮想環境で起動。週末の深夜に絶賛ダウンロード。ろくにミラーサイトの設定をしなかったのがまずかったのか、遅くてしかたありません。


PuppyLinux上のVirtualBoxにて実行中。パッケージマネージャが素抜けになっていますが気にしないでください。


とりあえずFirefoxを入れてみます。必要なコンポーネントを引っ張ってきますがそれを全部ループバックマウント(でいいのか?)するので、df を実行結果はなかなか壮観です。


バージョン33はLinuxMintの時と同じ。日本語パックをダウンロードしようとしたが失敗。仮想環境だからなのか、ネットワーク接続がいまいち安定しません。

等というより、そもそもキーボードやロケールがUSなのであらゆる作業がかなり大変。

いったい、どうなってしまうのか?


 

PuppyLinuxで常用しているツールの中に自作したラジオチューナーがある。自作と言っても、ネットを漁ってデコード方法や各局の接続先を探し、シェルスクリプトでつなぎ合わせただけなのだが。これをLinux mint 17.1 Xfce(64)で動かしてみた。

LinuxMint 17.1 Xfce(64)で不足していたのは次の通り。
1) swftools  swfextractをradikoで使用
2) beep   選曲時の確認音用
3) rtmpdump   radiko, らじるらじるで使用
4) mplayer   音出しの下請け。さらにAFNとNHKラジオニュースではURLを渡して丸投げしている。(昨日インストール済み)
5) gtkdialog 0.8.3  GUI構築用

このうち、1)から4)までは端末を開いてコマンド名を入力すると、存在しないものはapt-getで取り寄せるように指示が出るのでその通り実行すればよい。

問題は5)で、登録されていないようだったのでソースからビルドすることにした。(入手先はこちら)gtk2時代のツールであり時代遅れとは思うが便利な上に嵩張らないので入れておいても大丈夫だろう。

ビルドにあたってはlibgtk2-devが必要になる。これはSynapticを使ってインストールしたのだが、あれやこれやいろいろ連れ込んでくれたようだ。
PuppyLinuxで何かバイナリを作る時は prefixは原則/usr にしていたのだが、mint では念のため /usr/local にした。必要なのは本体バイナリとアイコンが一つだけなので、パッケージを作らずに手動でコピーした。そういえばmint でパッケージを作る場合は、単純にdebのままで良いのだろうか?

実際に動かすにあたってのPuppyLinuxとの相違点。
環境変数XDG_CACHE_HOMEが設定されていなかったので呼び出し前にexportした。また、mplayer の出力はpuppyではalsa (mplayer -ao alsa)だが、mint 17.1ではpulseaudio が動いているので -ao pulse に書き換えた。

pulseaudioだから、という訳でもないだろうが、デスクトップ上でのオーディオアプリケーションは一度起動するとどこかに記録されるようで、タスクバーのスピーカーアイコンから呼び出すことが可能である。これは便利かもしれない。もちろん、このラジオチューナーは相手にされない。念のため。


 

常用しているPuppyLinux 571JPは32ビットOSである。特に不具合はないが、Core2Duoを積んだハードで使っていると、「ああ、でもCPUの能力を100%引き出している訳ではないんだよなあ」という思いが募ってくる。
自分でバイナリを作るときはコンパイラオプションで、-mfpmath=sse とか -march=core2 -mtune=core2 -msse4.1 とかやってはいるが、カーネルやglibがi686(i486か?)互換のままでは結果に大差はない。気休め程度である。

では32ビット環境を捨てて64ビットへ移行するか、というと今度はハードが貧弱すぎて二の足を踏んでしまう。CPUはともかく、RAMが2GBしかない。これでは64ビット環境を100%堪能するという訳にはいかないだろう。

しかし、いつまでも64ビットバージン(?)でいる訳にもいかないので、とりあえずインストールして試用してみることにした。選択したディストリはLinuxMint 17.1 Xfce (64)である。Mintは以前もいじったことがあってデスクトップデザインが良かったので。当時は出始めのMATEを使ったのだが、最近はgtk3への移行が進んでいるとかで結局Gnome3環境と大差なくなってしまうのではなかろうか、と思ったので枯れているXfceにした。

日頃使わないサーバーから落としてくるせいかなかなか速度が出なくて1日がかりになってしまったが、30GB程度の空きパーテーション(LFSで遊んだ時の残骸)に入れた。ブートローダも一緒にインストールしたのでフラグがどうなるか不安だったが、PuppyLinux側のパーテーションに残ったので、grub4dosの設定ファイルに

title Linux Mint 17.1 Xfce 64-bit, 3.13.0-37-generic (/dev/sda5)
    uuid hogehoge
    chainloader +1

と書き足して2段階ブートとした。

で、1日かけて得られたのは日本語化が思いのほか難しい、ということである。ibus-mozcはダメで scim-anthy を動かすのがやっとだった。64ビット環境でもanthyの空気頭に付き合わされるのは勘弁してほしいものである。
デフォルトのFirefoxが33と旧いのでアップしたかったのだが自動でやらない。しかたないので手動で落として展開 /usr/lib/firefox へコピーした。Syncも動作するのだが、feedlyやμBlockといった一部の拡張機能が動作しない。64ビットだからか?

使い慣れたソフトが欲しい、ということで Audacious , mplayer, darktable, geany を入れてみるがどれも特に問題なく動作する。しかしLibreofficeを削除し代わりに入れたAOOはロケール問題で文字化けしてしまった。インストール先のprogramディレクトリにある soffice の冒頭に export LANG=C を書き足して解決した。我ながら何とも泥臭い。

いじっていて気づいたのだが、若干スワップが発生する程度まで使い込んでも動きがなめらかである。64ビットバイナリの本領発揮といったところか。

で、この記事はPuppyLinuxから書いている。日本語入力の問題が解決しないと実用にならないからね。まあ、せっかくいれたので気の向いたときに少しづつ使っていこう。
 

Pygtkにおける個人的な愚痴。

Pango を使って縦書き横書きを混在させたい場合、まず思いつくのが次の方法である。

' <span gravity="east" gravity_hint="strong">本日は晴天なり<span gravity_hint="natural" rise="-4000">it is fine today.</span>これでどうかしらん?</span>'

確かにこれでそれらしい表示はするのだが、いくつか問題がある。

まず、ベースラインが崩れる。同じ現象は<sup><sub>でもあった。英文にかかるspanでrise を打っているのはその調整。これがフォントサイズが変わるとディスプレイ上での効き具合が変わるという代物。
次に最初のspanの前に何でもいいから1文字打たなくてはならない。何故か? Pangoを解析した訳でないから想像になるが、ベースになる情報がないと文字の向きを変更してから具体的に書き出すことが出来ないようだ。なので捨て文字ともいえる1文字が必要になるのではなかろうか。なお、この1文字を省略すると後段のspanでの指定は動作しない。

一つの文字列の先頭にだけ捨て文字として空白を入れる程度ならば、マージンの調整で回避することもできる。しかし、実際問題としてマークアップを解析しながら表示する場合、タグで区切られるごとに処理する場合が多いのでその都度捨て文字が挿入されることになり、非常に具合が悪い。(処理を工夫すれば回避できるが)

で、これらを解決するには要するにPangoに初期情報を渡してやれば良い訳で、そのための関数が
pango.set_base_gravity('east') 及び pango.set_base_gravity_hint('natural')なのであった(引数は必要に応じて任意)。
以前よりpangocairo で描画する際、直前になってわざわざlayoutからpangoを作成してきてこの2つの関数を実行するのは実に奇妙な思いをしていたのだが、こういう理由があったのである。

が、うまい話ばかりではない。
今度はタグによる指定が一部無視される、という現象が生じるのである。いやはや。

開発者は充分な組み合わせテストをやっているのだろうか?それとも、縦書きはどこまでもオマケ機能に過ぎないのだろうか。


 


Search

Calendar

S M T W T F S
    123
45678910
11121314151617
18192021222324
25262728   
<< February 2018 >>

Archive

Mobile

qrcode

Selected Entry

Link

Profile

Search

Other

Powered

無料ブログ作成サービス JUGEM