地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Makefile】変数加工のtips

$(name:op%os=np%ns)

$(name)の各語に対し、先頭のopと末尾のosを削除して、先頭にnp, 末尾にnsを付加する。

用途としてはこんな感じ。特定ディレクトリ配下のファイルを取得して指定したパスに加えて拡張子をつけるみたいなケース

vars := $(filter-out Makefile, $(shell ls -1))

all:
   @echo $(vars:%=/tmp/%.txt)

上記に適当なファイルを作成しておくことで実行すると以下のようになる。ローカル -> Linuxの実行パスにファイル名を変えつつ動的に配置するファイルを決定させたいケースみたいなので便利。

make
/tmp/dep.yml.txt /tmp/pv.yml.txt /tmp/pvc.yml.txt

【Perl】CによるPerl拡張 XSに入門する

概要

休み明け一発目から古のperlを使った謎モジュールのビルドエラーの確認作業になった。cもmakefileもそれなりに読めるし余裕だろって思ってたらそんなことはなかったのでメモ

XSでハマったというよりはそもそもXSが何なのかをそんなに理解してなかったので理解用に書く

XSとは

XS は Perl と(Perl と一緒に使いたい)C のコード(または C ライブラリ)との 間の拡張インターフェースを作るのに使われるインターフェース記述 ファイルフォーマットです。 
XS インターフェースはライブラリと動的または静的にリンクされて、 Perl とリンクすることのできる新しいライブラリを生成します。 
XS インターフェース記述はは XS 言語で書かれており、 Perl 拡張インターフェースのコアコンポーネントです。

perldoc.jp

XSはCをベースに独自のマクロを持った言語。PerlからCコードを呼び出すぐらいにしかわかってなかったけどリファレンス読むと思ったより高機能なのが分かる

XS 言語の特徴

拡張子は(.xs)でファイルの中にはC言語ソースコードとXSUBが含まれます。XSUBはXSで言語で書かれC言語の関数にぱっと見は似ています。正直拡張を見ないとCの独自仕様かな?と思うくらいには似ているので理解するのも難しいです。

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"


MODULE = SomeModule       PACKAGE = SomeModule  

なのでXSを取得するにCとPerlあたりの知識が必須となっている。

使ってみる

minilという雛形生成ツールを使って最小コードのxsを生成してみた。

qiita.com

ぱっと見はC。SVとかその辺はそのままperlの用語に紐づく形となっている

#ifdef __cplusplus
extern "C" {
#endif

#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#ifdef __cplusplus
} /* extern "C" */
#endif

#define NEED_newSVpvn_flags
#include "ppport.h"

MODULE = Acme::MyModuele    PACKAGE = Acme::MyModuele

PROTOTYPES: DISABLE

void
hello()
CODE:
{
    ST(0) = newSVpvs_flags("Hello, world!", SVs_TEMP);
}

SVの操作

XSからPerlのデータを操作する方法

SV の中身をダンプして出力

sv_dump(sv)

新しい SV をつくりたい。整数値から SV をつくりたい

SV* sv = newSViv(5963);

符号なし整数値から SV をつくりたい

SV* sv = newSVuv(5963);

文字列から SV をつくりたい

SV* sv = newSVpvn("hello", strlen("hello"));

SV から SV をつくりたい

SV* new_sv = newSVsv(sv);

SV の値が真か偽かがしりたい

bool b = SvTRUE(sv);

sprintf したい。

SV* sv = newSVpvf("%d", 3);

参照カウンターをインクリメントしたい

SvREFCNT_inc(sv);

参照カウンターをデクリメントしたい

SvREFCNT_dec(sv);

ppport.hのインターフェース

metacpan.org

PerlのC APIを呼び出すことでPerlのデータ構造に対する操作を行う事ができるのはなんとなく上まで書いていて理解はできました。CのAPIPerlの歴史が経つにつれて変わっていくのが上記のCPANで公開されているモジュールから見て取れます。

モジュールを使うことである程度の変更は吸収してくれるようですが例えばperl5.10で追加された関数を使ったモジュールを5.8のperlでビルドしようとすると失敗するみたいなことは往々にして起き得ます。

仮に存在しない関数を使った場合この辺はビルド時にエラーになるので関数名がわかったら上記のcpanchangelogを眺めてどこで追加されたのかを確認するのが良さそうです。

参考

xsubtut.github.io

tutorial.perlzemi.com

【Go】ベンチマーク ツールのtips

golang.org

  • -benchmem

メモリ関連の情報を出力。

  • -benchtime t

計測に使う時間をtで指定する。defaultは1s

  • -cpuprofile=*.prof

詳細なCPUプロファイルが取れる go tool pprofで内容を見る

  • -count

テストする回数を指定

  • -cpu

実行するcpu数

  • -memprofile=*.prof

詳細なMemoryプロファイルが取れる go tool pprofで内容を見る

【Docker】パッケージアップデートのベストプラクティス

pythonspeed.com

必須パッケージが古いことがわかっている場合は、ベースイメージのメンテナーに連絡した上で、アップデートするみたいなのがベストプラクティスってなっていたけど最近は上記の記事で言っているように違うらしい

hadolintで検証

検証用Dockerfile

FROM debian:9

RUN apt-get update && apt-get upgrade

古いやつ

$ hadolint --version
Haskell Dockerfile Linter 1.18.2-no-git

$ hadolint Dockerfile
Dockerfile:3 DL3005 Do not use apt-get upgrade or dist-upgrade
Dockerfile:3 DL3009 Delete the apt-get lists after installing something

最新。確かにアップデートは使うなという警告は無くなっている

$ docker container run -it hadolint/hadolint hadolint --version
Haskell Dockerfile Linter v2.3.0-0-g96e61f8

$ docker container run -i hadolint/hadolint < Dockerfile
-:3 DL3009 info: Delete the apt-get lists after installing something

ルールについての説明もリポジトリを見にくと確かに変わっているのがわかる。

github.com

ベースイメージでユーザが切り替わっている場合は再度スイッチしてrootでアップグレードした上でユーザを切り替えよう的な感じらしい。

そもそもディストロはいるのか

最近というか昔から言われているのがディストロ不要説。セキュリティ的にパッケージアップデートが必要なのは理解できるがそもそもセキュリティホールになるようなパッケージなりバイナリなりをおく必要があるのかという話。デバッグ用途でそれなりのコマンドを入れておくのは良さそうだけど本番運用するならいらないのかもしれない。