モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

SSDの寿命に関して再度

なにやらIntelからOptane 800pが出るとのことで 買おうかな〜と思って調べたら、TBWがなんか365TB?ぐらいしかないのですね。 3D XPointメモリは寿命1000倍と聞いていたのだけど、これだと5〜10倍程度なのでは?という。

うーむ。Optaneディスクを使ってもうtmpfsに頼らない、気兼ねなく/varとかにも書き込めまくるシステムを構築したかったのだけど。 これだと、安いSSDを5年ぐらいで買い換えるのがベストな気が… なにせ、Optaneディスク自体の寿命も永遠ではないわけだし。5年以内にぶっ壊れたら、まじに無意味。

そこで今使ってるSSDの寿命ってどんなもんだろと、再び気になって来たのですね。 そこで再度自作スクリプトで計算してみる…と。

残り寿命1000年ぐらいのがでたんですけどw

いやいやいくら何でもおかしいだろ…と思ってよく見ると 拙作スクリプト、TB単位の値を返してきた時の場合を考慮していない。 dumpe2fsが表示しているのには「13 TB」とある。 一年半で13GBしか使わないわけねーだろ、っていう…ハハハ…(自分、クソダサすぎ…w)

てか一年半で13TB!?!?!? 一日24GB!?!?!

おったまげましたな…自分にはあり得ない数字だわこれは…

何もろくにダウンロードしていないし、OSアップデートが時折数百メガ単位であるけど、これはシステム側128GBのSSDのはず。 そしてブラウザのダウンロードフォルダはHDDに設定してある… 最も消耗するであろうお絵かきはHDD上でしているし。その他、プログラム書くのはさほど負荷にならない…ハズ

ものすごい気を配って減らしてきたのに…

心当たりといえば…そう言えば、youtubeフルHDのバスや電車の前面展望動画を毎日のようにBGVとして再生している…

これかな。

っといいたいのだけど、ワタクシ実はほぼfirefoxしか使っておらず、そしてfirefoxのみならず .cacheフォルダ自体をbindマウントしてhddとtmpfsなramdiskに割り振っているのですなぁ。

よ、要するにdumpe2fsってつまり… bind mountされると正確な書き込み数が得られないのでは…

ということにようやく気づきましてですね。

そういうわけでググッて得たpocket8137様のこちらの情報

qiita.com

ここの、コメ欄、sharow様の話よりsmartctlでファイルシステムに頼らない書き込み数が得られると聞きつけ。 さっそく自作スクリプトを更新したのでありました。 てかもうsharow様のこのツール

github.com

これを使えばいいんだけどw(高機能だし) なんか意地でwww 拙作では、TBWをデバイス毎にjsonファイルに書いておいてそっから寿命を推測するという方式にしました。

そうするとやはり累計書き込み量は一年半で500GB程度と超・控えめな数値が算出されましたw

残り寿命は今後1日に書き込み数が激増して20GB書いたと仮定しても30年近くあり、まぁ十分だろうと。

ちなsmartctlから得た情報を総合すると、/homeのmx300は日に1.7GBぐらい書いているので、220TBWとして推定残り寿命400年以上www

システムの東芝HG6q?だかの128GBはTBW不明なので36TBWと仮定し、日に0.5GB程度で推定寿命181年w これ、もう4年は使ってるっぽいのですが。以前、60GBのSSDを使ってた頃は/var等もHDDに移すほど神経質に使っていたのですが、コレに変えてからはそれよりかは気楽に使っているのです。 せいぜい、/var/tmpだけはtmpfsにしているぐらいで…ああ、あと/var/logのログも控えめに出力する設定にしてありますか…

ブラウザのキャッシュはさすがにこのままの路線で行くとはいえ、 システムを75TBWぐらいの普通の240GB SSDにしても、無設定で十分に何も気にせず使えますなコレ。 というかもうブラウザ対策だけでよい?

というか逆にOptaneの365TBWが輝き始めたというか、なんかキャッシュ的にゴリゴリ使えそうじゃないすか逆に。

ちなみに、ワタクシが最も容量を消費している趣味のお絵かきですが、去年のお絵かきのフォルダは合計7GBでしたw 1ドキュメントにつき50回ぐらいは上書き保存していると荒く計算すると、350GBか…あまり安全な数値ではないですね。まぁ実際には失敗に備えて名前つけて保存のほうも多そうだから、こんなに上書きして無いと思いますが。

余談ですがワタクシ、お絵かきにおいては通常全く使わないF1キーを上書き保存に割り当ててワンキーで気軽に保存しまくっています。ただ、心理的な安堵感こそあれ、それが役に立ったことはほぼありません。

つぅかそもそもお絵かきについては、HDDでも速度的な不満を全く感じていない罠。

Xubuntu(Ubuntu+xfce)16.04でのトリプルモニタ環境の設定

Xubuntu 16.04 (≒Ubuntu + xfce) 、今までデュアルモニタ環境で快適に使っていましたが、実はコレ偶然の産物だった…という話。

前述のようにwacom cintiq13HDを導入したため、トリプルモニタ環境にしたのですね。ちなみにGPUnvidiaGeForce 750GTXです。 それで設定したままサスペンド運用してきて、今日IHコンロやら何やらの使い過ぎでブレーカーが落ちて停電しました(^^;

やはりIHはクソ。地球上から駆逐されるべき存在。今すぐガスに戻せ

なんて話はどうでもよくて、んでリブートしたらファイルシステムがcorruptしていて立ち上がらない…のは仕方なかったのでfsckしてなんとか立ち上がるようにはなったのでまあよいとして、

リブートしてようやく思い知ったことはといえばnvidia-settingsを使っても

全然トリプルモニタ環境を覚えてくださらない…

ということです。

しかし… nvidia-settingsのモニタ設定ってどっかに記録されるわけじゃないんですね。*1今までのデュアルモニタ時代は、偶然に上手いこと設定が自動で行われた…というだけのことのようです。ただのおまけユーティリティなのでしょうか。(立派に見えるのでついつい使ってしまいますな〜)

それにつけても、まずはHDMI-0、つまり通常電源を入れていないcintiqがプライマリにされてしまうようで、ログインダイアログが見えない。これはきもい。

これについては、ググった結果「~/.config/monitor.xmlなる謎のファイルが悪さをしている」という話があったので、一応リネームで様子を見ることに。 確かにこれでDisplayportがプライマリになり、無事メインのEIZO EV2436Wにログインダイアログが出るようになりました。

しかし…この状況下でも、なんか、cintiqとサブモニタが重なって右に表示されてしまうのですね。つまり「サブのみクローン」状態。

ただし、これはこれで実際便利な気もします。 デュアルモニタ状態で実質トリプルのほうが、色々とっちらからなくて宜しい、という考え方ですね。むしろプライマリに重ねてしまうという手もあるのかも。 *2

ただ、トリプルモニタ環境を思ったとおりに構築可能な状況で「サブのみクローンのが便利じゃん」って移行するのなら良いのですが、せっかくLinuxを使っているのに妥協はよくない、ということでさらに調べる事に。

んで色々諦めて最後の望みとして、絶対確実なはずの方法、つまりxfceの「自動起動アプリケーション」でxrandrを呼び出すスクリプトを書いた…しかし!

なんと、これも機能してくださらない!

/tmpに標準出力を書きだしたところ、呼び出しは行われていて直後のxrandrでは正しく設定が行われている。しかしその後何者かによって設定が書き換わって居る模様。

調べた結果どうも、xfceの設定が直後に行われているっぽいのです。

結論としては…

xfceでの作法としては「設定」→「ディスプレイ」で出るミニ設定アプリでモニタ設定するのが、恒久的にモニタ設定を記憶させる正しい方法のようです。

f:id:dothiko:20180112142827j:plain

このアプリですね。*3

ではそういうことで(疲れた…)

*1:固定化の為にxorgのconfを吐いてくれるらしいのですが、何かパッケージが足りないのか吐いてくれなかったし、それ以前に今の時代にxorg.conf.dにモニタ設定というのも…

*2:てゆーか色々買って不良品も掴んでみたHDMI分配器、あらゆる面で完全に要らなかったな。ハハハ…

*3:正直いままで「このディスプレイってのはつかえねー設定アプリだな…」と思っていましたが私が間違っていたようです

Gesturefyとevdevで作る快適3ボタンマウス環境

FirefoxプラグインFiregestureが使えなくなったため、Gesturefyを導入しました。 これがまた、なかなか良い。

なお、ジェスチャー&ロッカージェスチャー*1は、現時点ではlinux/macにおいては、右ボタンが押下時にコンテキストメニューを発動するため、コンテキストメニュー発動を回避できず、右開始のジェスチャーはまともに使えません。 しかしながら、これはver 58以降のfirefoxでは改変されるそうなので非常に楽しみです。 *2

それまでの間は、ジェスチャーは左ボタンで起動することにしました。うっかり範囲選択を始めるとジェスチャーに入ってしまうのですが、Gesturefy設定によるジェスチャーの無効化「Ctrl押下でキャンセル*3」と、「一秒じっとしてればキャンセル」を併用すれば実用上問題はないので慣れの問題ではあります。 まぁ、早く来てくれ右ボタンー!! としか言いようがないのですが。

ともかく、それで戻るボタンが不要になったため、3ボタンマウスm100rではevdevのホイールエミュレーションを中ボタンに割り当ててみました。

xinput --set-prop ${id} 'Evdev Wheel Emulation' 1
xinput --set-prop ${id} 'Evdev Wheel Emulation Button' 2
xinput --set-prop ${id} 'Evdev Wheel Emulation Axes' 6 7 4 5
xinput --set-prop ${id} 'Evdev Wheel Emulation Inertia' 2

これやると2ピクセルぐらいで1スクロールになるので超かっとび・超快適です。

マウスホイールなんか要らなかったんや!と言うレベルの…いや、実際にはあったほうがいいの…かな…細かい動きを指定したいときは、やっぱりまだ役に立ちますかね。

できれば遅く動かしたときはイナーシャを大きくする仕組みがあればなぁ、と…まぁ、いいか。

となってくるとコレ、ミドルボタンをサイドに取り付けた私の改造マウスではなく、むしろ無改造の3ボタンのほうが使いやすいのでは?という疑問が沸いてきましたが まぁ「それはそれ」ということで。てか、ホイールクリックの反応の悪い事を考えれば、サイドもわるくはないです。

試しに、以前買ったナカバヤシのMUS-UKF90NBKで、サイド「進む」にホイールエミュレーション、 「戻る」にミドルボタンをマップしてGesturefy発動という設定にしたところ、これはこれでかなり快適でした。

いままで、自分の手に対してホイールの位置が合わないことでサプライ系各社の安マウスには大変苦しめられてきましたが。

それでもLinuxのevdev環境下においては、5ボタンあればホイールは本当に補助的になるため、今後はサプライ各社の安マウスを導入しても全く問題ないという事がわかってきました。

つぅかね…大昔3ボタンだけのホイール無しのシンプルマウスがあったじゃないですか。*4

アレでいいと思うんですよ。

んでevdevのようなドラッグによるホイールエミュレーションをハードウェアレベルで入れてしまえばいい。 だからセンターは都合2ボタンになりますが。フリースピンホイールとどっちが速いかはわかりませんが…操作性考えれば、かなりいい勝負になると思います。

更に言うとサイドに戻る進むも付けた、6ボタンホイール無しマウス。そりゃ10ボタンぐらいあれば言うことないですが、ここは敢えて限界までそぎ落として6ボタン。

これ最強だと思うんですがどうか。

*1:マウスボタンを右→左で同時押し/左→右で同時押しでそれぞれ別の機能を発動するジェスチャー

*2:なお、現段階でも、ロッカージェスチャーの右→左で「戻る」を行いたいときは、コンテキストメニューが出たままで左ボタンをダブルクリックすると「戻る」が発動されます。

*3:Shiftも設定できるのですが、何故か範囲選択できない場合が多い

*4:今もあるようですが中身に比して超ボッタクリな感じが…とくにHPのやつ

Blenderが起動しないように見えるとき(@トリプルモニタ環境)

遅ればせながら、あけおめことよろでございます。

さて私のPC環境は大きく変化し、Wacom cintiq13HDを導入したことでトリプルモニタ環境となりました。 ちょっと変則的ですが、正面と右にモニタを配置。これは今までと同じ。 次に、正面の下…つまり机の上にcintiq13HDを置くという形になります。

これで自然にマウスカーソルを主画面の下に動かすと、cintiqの中にカーソルが入ってくるというようになりました。 そして、貧乏性が災いし、cintiqは通常HDMIに接続されているものの、電源は落としてあります。この状況下で、XWindowシステムにモニタとして認識はされ続けており、トリプルモニタ環境は継続しています。

見えるかどうかだけの違いであり、cintiqの電源を投入すれば、USBのペンタブデバイスプラグインされるだけで、モニタとしてはシステム上、ほぼ何も変化なしに、単に画面が見えるようになるという、理想的な状況です。

さてここで問題が発生しました。

Blenderが起動しない(ように見える)

この状況下で、何故かBlenderが起動しない。画面が全く見えない。 psで見るとプロセスは発生している。

Alt+Tabを押すとやっぱりあるなぁ。

そこでwmctrl -lGすると。やはり、ウィンドウは出ています。しかし、位置が…cintiqのなかにいる!

デュアルモニタではせいぜい2つの画面にまたがるぐらいなのですが、どうも変則的なシステムだと「最初に見つかるモニタ」に行く傾向がある模様であり、我がシステムではそれはHDMIだという…それが今回の悲劇を生んだようです。

Blenderウィンドウが動いてくれない。

調べると-pオプションを与えることで起動位置を指定できるようです。

しかし、これがまた何故かサイズだけ適用され位置が機能しない。 orz

追記:と思ったらワタクシ間違えておりました。詳細は下の「Blenderの-pオプションの正解」に書いておきました…が、一応wmctrlの効かない状況で、xdotoolでウィンドウを移動するためのサンプルとして以下に残しておきます(^^;

仕方ない、wmctrlで移動させるしかないか…

…ところが、wmctrlの-eオプションではBlenderのウィンドウを動かすことが出来ないようです。 (コレは実はKritaも同じで、xdotoolで移動できます)

仕方ないので、xdotoolを使用します。 というわけでスクリプト化してみました…

#!/bin/sh
width=1920
height=1200
x=0
y=0
title="Blender"

blender -p $x $y $width $height &
sleep 1
id=`wmctrl -lG | grep ${title}\$ | cut -f 1 -d " "`
xdotool windowmove $id $x $y

後々汎用化させることも視野に入れ、大体のところは変数化しました。

Blenderの-pオプションの正解

何気なく再度manpageを見ると…

       -p or --window-geometry <sx> <sy> <w> <h>
              Open with lower left corner at <sx>, <sy> and width and height as <w>, <h>

lower left corner って書いてあるわw

だから正解はwmctrlやらxdotoolやらを使うのではなく、pオプションだけ、

blender -p 0 1200 1920 1200

で良いということになりますな…相変わらずアホなワタクシでございます。

おまけ - Blenderでマウス中ボタンを代用する

ワタクシ、また安マウスを購入する病気が発症しそうで苦しんでいるのですが、Blenderでは中ボタン(ミドルボタン)でビューを操作できるのが重宝されているようです。

それでもって私はマウスのミドルボタンを改造して側面に付けて別のことに使っているのでした。 以前は戻るボタンに割り振っていましたが、FirefoxのGesturefyを導入して以来、「戻る/進む」はジェスチャー(ロッカージェスチャーも)で代用できるようになったため、 現在はevdevによる、ドラッグでの快速なスクロールエミュレーションに使用しています。 つまり、ボタンが足りません。 このため、またも5ボタン以上のマウスが欲しくなり禁断症状が発症しているのでした。

そんなわけでミドルボタンを代替する方法はないものか、と調べたらあっさり見つかりました。

User preferences -> Input -> Emulate 3 button mouse

これをチェック入れるだけでAltキー押下+左ボタンでビューをグリグリ回せるのですね。とりあえずはコレで行きます。

SWIGオブジェクトから生のポインタを取り出すには

最近SWIGづいていますが… PythonSWIG(SWIGPythonか…?)ラッパーオブジェクトからポインタを取り出すにはどうすればいいのか?

それも、自作のクラスオブジェクトでございます。 なんでこんなことをする必要があるのかというと、SWIG化クラス「foo」があるとして…

import swig_module

bar = []
for i in range(10):
    bar.append(swig_module.foo()) # fooクラス生成

swig_module.call_swig_list(bar) # リストを突っ込む

こんな感じの時ですね。fooインスタンスは、pythonで何かするためにやむをえず作ったリスト配列の中に入っており。 それでcall_swig_listの中で取り出すと、それはPyObject* なわけです。

ここから、C++クラス「foo」のポインタを取り出して、C++コードの中で呼びたい。

「各fooインスタンスを引数にしてforループの中で呼ぶようにすればいい」という状況のほうが多そうですが、そうも行かないことがある。 まぁ例えば大量のfooインスタンスがdictの中に入っていて、そのキーも重要な情報だったりするので一遍に処理したいとか。

正直、ただのこだわりです。

結構苦しめられましたがわかりました。

  • SwigPyObjectという型(構造体)があるのだけど、これが.ccという拡張子のSWIGによる自動生成ファイルに入っている。
    • .ccファイルの中は、非常にマクロ宣言が多くキモい。
  • だから手っ取り早く使うにはもう自分で定形のを宣言してしまうのが良い。
typedef struct {
  PyObject_HEAD
  void *ptr;
  void *ty;// Dummy definition. Actually, this is swig_type_info*. 
  int own;
  PyObject *next;
  PyObject *dict;
} SwigPyObject_base;
  • さてこのptrというのがそのオブジェクトポインタか…といえばさにあらず。
  • 実は、SWIGがデフォルトでサポートしていない型の場合、露出するオブジェクトの「this」属性に、生ポインタを保持したSwigPyObject*が格納されるという、2段階構造になっている。

やっと動いたテスト用のSWIG関数だけ抽出して書いておきます。

PyObject* call_swig_list(PyObject* pylist) {
    int length = PyObject_Length(pylist);
#if PY_VERSION_HEX >= 0x03000000
    PyObject* swig_this = PyUnicode_FromString("this"); 
#else
    PyObject* swig_this = PyString_FromString("this");
#endif
    for(int i=0;i < length;i++) {
        SwigPyObject_base* o = (SwigPyObject_base*)PyList_GetItem(pylist, i);
        // Make shadow instance as real instance.
        o = (SwigPyObject_base*)PyObject_GetAttr((PyObject*)o, swig_this); // new reference.
        foo *f = (foo*)(o->ptr);
        printf("objectptr %lx \n" , f);
        f->method1(i); // これでクラス「foo」のインスタンスのメソッドを呼べる!
        Py_DECREF(o);
    }
    Py_DECREF(swig_this);
    Py_RETURN_NONE;
}

多少、強引ですが…動けばよかろうなのだァァァァッ!!

…って、動けばよかろうなら最初に書いた「python側でforループ展開」でいいだろ、って気が自分でもしますが(^_^;)

ともかくこれをつかって…ヌフフ

Gdk(pygi)でマウスカーソルを任意位置に動かすには

感動のあまりカキコ!

改造版mypaintのsizechangemode.pyから一部抜粋〜

    def drag_start_cb(self, tdw, event):
        self._ensure_overlay_for_tdw(tdw)
        self._queue_draw_brush()
        # Storing original cursor position and some needed objects.
        dev = event.get_device()
        pos = dev.get_position()
        self._dev = dev
        self._scr = event.get_screen()
        self._ox = pos.x
        self._oy = pos.y
        super(SizechangeMode, self).drag_start_cb(tdw, event)

    def drag_update_cb(self, tdw, event, dx, dy):
        self._ensure_overlay_for_tdw(tdw)
            
        self._queue_draw_brush()
        adj = self.app.brush_adjustment['radius_logarithmic']
        cur_value = adj.get_value() + (dx / 120.0)
        adj.set_value(cur_value)
        self._queue_draw_brush()
        super(SizechangeMode, self).drag_update_cb(tdw, event, dx, dy)

    def drag_stop_cb(self, tdw):
        self._ensure_overlay_for_tdw(tdw)
        self._queue_draw_brush()
        self.start_drag = False
         
        self.base_x = None
        self.base_y = None

        # Reset cursor positon at the start position of dragging.
        Gdk.Device.warp(self._dev, self._scr, self._ox, self._oy)
        super(SizechangeMode, self).drag_stop_cb(tdw)

概要としては

  • event構造体のget_device(), get_screen()が必要。
  • mypaintのdrag_stop_cbにはeventがないので保存しておく
  • 位置はスクリーン座標なのだけど、deviceオブジェクトのget_position()でなんか謎のオブジェクトが得られてそいつの属性x,yがスクリーン座標なので、それを保存しておく。
  • ドラッグ終了時にGdk.Device.warpですっ飛ばす

これで、いままでシフトキー押下で発動するように設定していたオンキャンバスなブラシサイズ変更モード。

これが、サイズ変更でカーソル動いちゃって悲しい感じだったんですが (kritaを真似したのだけど、あっちはちゃんとカーソルが固定される)

ようやく思い通りになりました!

追記:

…と、マウスで実験してみた時は良かったのですが… ペンタブでやってみると、やはりペンタブを動かしてサイズを変更するとカーソルが移動してしまう。 ナンデ? と思ってよくよく考えてみると…

> ペンタブは絶対位置デバイスだから離した瞬間に別の絶対位置に移動している <

という、実にマヌケな結果に… じゃあ、Kritaはどうやってそれを防いでいるのか?

と思ってやってみたら(当たり前ですが)Kritaでも同じ挙動でした(>_<) 記憶が間違っていただけという悲しい結果に。

SWIG関数にctypesからアクセス

ついでにこれも思いついたシリーズ。

すなわち例えば、SWIG側の内部にstaticで構造体ポインタのリストを持っておき。 idx = register_hogehoge(void *ptr)でそのリストに登録。 その後はidxを使って(OpenGLのテクスチャの名前みたいな感じで)、例えば draw_bg(idx, 0, 0) みたいなことをすると。まぁ、これだとオブジェクトが削除されたのを知るのは難しそうなので、そのへん十分に気を使って、と。 どうにかすればctypesのオブジェクトにincref的なことができるのかもですが、まだよく分かっておりません。 あ、ていうかよく考えると表面はPyObjectだろうから普通に行けちゃったりするのかな…

ともかく、そういういうことを思いついたのでやってみました。 特に普通の共有ライブラリと違う点もなく、簡単にできました…ポイントは * ctypesの名前関係が難しくなるのでextern "C" でその場を凌ぐ * void*だと、構造体を引数に入れただけだと自動変換してくれないっぽいので、pointer(obj)を使う * つかcast(pointer(obj), c_void_p)が正しい? まぁLinuxだから簡単だったのかも知れないですけどね。

その他、ctypesの関数にSWIG内から…というのも妄想していましたが、よくよく考えると上記の「SWIGをctypesで呼ぶ」作戦のほうが柔軟性も自由度も高そうなので、とりあえずこれでいいかなと。

最初に思いついたのはctypesでポインタをlongにする関数を作って呼び出し、SWIGでそのlong値を受けてそれを強引に構造体ポインタにキャストする…というものでした。実際に動いたのですが、実になんかその…ダサいというか無理矢理感が強すぎたので上記の方法を考えました。

もしかするとswigに直接ctypesの構造体のアドレスをvoid*ポインタとして送り込めるのかもですが、そのへん全然わからないのでした。