odz buffer

2016-02-15

git の sha1_to_hex のやつ

すこし調べた。

Linus が普通に Mailing List で明言していた。

Nothing magical, it's just "rounded up from 40 + NUL character".

[PATCH] hex.c: reduce memory footprint of sha1_to_hex static buffers

単に、40バイト+NUL文字用の1バイトで切り上げて50バイトらしい。

が、masterのやつを見たら全然違うので、もう少し歴史を見てみる。

最初のは read-cache.c にあった。initial commitですね。

char * sha1_to_hex(unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	return buffer;
}
read-cache.c

sha1_file.cに移動されたあと、ちゃんと毎回 NUL terminate されるようになる。commitは@1e80e0

char * sha1_to_hex(const unsigned char *sha1)
{
	static char buffer[50];
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
sha1_file.c

static 領域のアドレスを返すためにエラーメッセージ作るのが面倒だとかそんな感じの文句が出たのか、簡易LRUキャッシュが導入される。commitは@dcb345

char * sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][50];
	static const char hex[] = "0123456789abcdef";
	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
	int i;

	for (i = 0; i < 20; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
sha1_file.c

さらに hex.c に移動して、マジックナンバーマクロで置き換え、バッファサイズも変更。commit は @aa1c6f

char *sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
	static const char hex[] = "0123456789abcdef";
	char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
	int i;

	for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}
hex.c
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
cache.h

で、reentrant版の sha1_to_hex_r と非reentrant版のsha1_to_hexに分離して、だいたい今の形になっている。commitは@af49c6

char *sha1_to_hex_r(char *buffer, const unsigned char *sha1)
{
	static const char hex[] = "0123456789abcdef";
	char *buf = buffer;
	int i;

	for (i = 0; i < GIT_SHA1_RAWSZ; i++) {
		unsigned int val = *sha1++;
		*buf++ = hex[val >> 4];
		*buf++ = hex[val & 0xf];
	}
	*buf = '\0';

	return buffer;
}

char *sha1_to_hex(const unsigned char *sha1)
{
	static int bufno;
	static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
	return sha1_to_hex_r(hexbuffer[3 & ++bufno], sha1);
}
hex.c

こんな小さな関数でも結構変わっているもんですな。

2016-02-11

近況

唐突にしばらく都内勤務になった。とりあえず、3月までの期限付きの予定。

s/20/40/

どうみても、40バイト書いていると思う。

2016-02-07

データがずれている

ブコメにも書いたけど国立大学の授業料のデータが5年ずれているっぽい。昭和50年1975年ですからね。

というだけなのもなんなので、ちゃんとデータをまとめてみた。

1975年比でいうと、物価で補正すると8.26倍、給与で補正すると5.92倍になっとると。

注意点

  • 授業料のデータは文科省のページから
  • 物価政府統計から「持家の家賃帰属を除く総合」
  • 給与は厚労省のページの所定内給与を使った
  • 1975年の所定内給与のデータがないようなので、1976年、1977年のデータから線形補間
  • 2006年以降の授業料のデータがなかったが、変わっていないようなので、2005年のデータのままとした
  • 一部手打ちしているので、間違っているかも

2015-06-09

[]Emacs Lispでvariance

Lispらしく書くならこんな感じ?

(defun varp-1 (xs)
  (cl-labels ((varp-sub (xs s1 s2 len)
			(if (consp xs)
			    (let ((x (car xs)))
			      (varp-sub
			       (cdr xs)
			       (+ s1 (* x x))
			       (+ s2 x)
			       (1+ len)))
			  (let ((e1 (/ s1 (float len)))
				(e2 (/ s2 (float len))))
			    (- e1 (* e2 e2))))))
    (varp-sub xs 0 0 0)))

慣れないと読みづらいな。Python で書きなおすと、こう。

def varp_1(xs):
    def varp_sub(xs, s1, s2, length):
        if xs:
            x = xs[0]
            return varp_sub(xs[1:], s1 + x * x, s2 + x, length + 1)
        else:
            e1 = s1 / float(length)
            e2 = s2 / float(length)
            return e1 - e2 * e2

    return varp_sub(xs, 0, 0, 0)

Emacs LispはTail Call Optimization効かないのでdolistマクロのが一般的かも。

(defun varp-2 (xs)
  (let ((s1 0)
	(s2 0)
	(len 0))
    (progn
      (dolist (x xs)
	(progn
	  (setq s1 (+ s1 (* x x)))
	  (setq s2 (+ s2 x))
	  (setq len (1+ len))))
      (let ((e1 (/ s1 (float len)))
	    (e2 (/ s2 (float len))))
	(- e1 (* e2 e2))))))
(benchmark-run 100 (varp-1 large-list))
(0.009979 0 0.0)

(benchmark-run 100 (varp-2 large-list))
(0.00844 0 0.0)

dolistを使ったほうが少し早い。

2013-08-24

初めての Pull Request

GitBucket に3件ほど Pull Request を送っておいた。OSS への Contribute は久々な気がする。

Scalatra 知らないし、Scala は書籍持っているけど、ほとんど経験ない、とかいう状態だけどなんとかなるものだな。

#86 Add encoding detection

Shift-JIS で書かれたファイルをレポジトリに入れると表示がおかしい、ということで、エンコーディングの自動認識+変換。

コードを見ると、UTF-8 決め打ちでバイト列から文字列に変換していたので、juniversalchardet を使ってエンコーディングを認識して変換するようにしただけ。

#87 Specify ContentType

なぜか、IE だとまったく表示されない問題の対策。

最初、さっぱり分かんなかったんだけど、間に WEBrick で作った proxy はさんで、ヘッダを確認して判明。リクエストの Accept ヘッダに application/x-shockwave-flash があって、text/html がないとレスポンスの Content-Type が application/x-shockwave-flash になっとる。なんだこれ?

とりあえず、明示的に Content-Type を指定するように変更。

しかし、IE の Accept ヘッダが変。

Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, */*

image/pjpeg ってなんだ?

#88 Support i18n

国際化の仕組みいれただけ。あとはメッセージリソース作って、テンプレートを書き換えれば多言語対応出来るはず。

個人的には必要ないんだけど、UI が英語なだけで拒否反応示す人もいるからねぇ。