abのベンチをあげるコード
昨日ぐらいからcpu profilerと戦いつつ、うんうん考えてた方法。
思いついた方法と同じような事をnginxもやってて「やっぱそうなるのか」といった感じ。
で頂きました。
ぶっちゃけインチキコードじゃないかなあと思う。
とりあえず、時間を引っぱる処理はそれなりにもっていかれるのでそれをいかに少なくするかという話。
(localtimeがCPUを持っていく)
つーかあってるのかも微妙な感じだけど。
time_cache.h
typedef struct { time_t sec; uintptr_t msec; int gmtoff; } cache_time_t; void cache_time_init(void); void cache_time_update(void); extern volatile char *err_log_time; extern volatile char *http_time; extern volatile char *http_log_time;
time_cache.c
#include <inttypes.h> #include <time.h> #include <sys/time.h> #include <stdlib.h> #include <stdio.h> #include "time_cache.h" #include "atomic.h" #define TIME_SLOTS 64 static uintptr_t slot; volatile uintptr_t current_msec; volatile cache_time_t *_cached_time; volatile char *err_log_time; volatile char *http_time; volatile char *http_log_time; static cache_time_t cached_time[TIME_SLOTS]; static char cached_err_log_time[TIME_SLOTS] [sizeof("1970/09/28 12:00:00")]; static char cached_http_time[TIME_SLOTS] [sizeof("Mon, 28 Sep 1970 06:00:00 GMT")]; static char cached_http_log_time[TIME_SLOTS] [sizeof("28/Sep/1970:12:00:00 +0600")]; static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; void cache_time_init(void) { _cached_time = &cached_time[0]; cache_time_update(); } #define get_timezone(isdst) (- (isdst ? timezone + 3600 : timezone) / 60) void cache_time_update(void) { time_t sec = 0; uintptr_t msec = 0; char *p0, *p1, *p2; cache_time_t *tp; struct timeval tv; gettimeofday(&tv, NULL); sec = tv.tv_sec; msec = tv.tv_usec / 1000; current_msec = (uintptr_t) sec * 1000 + msec; tp = &cached_time[slot]; if (tp->sec == sec) { tp->msec = msec; return; } if (slot == TIME_SLOTS - 1) { slot = 0; } else { slot++; } tp = &cached_time[slot]; tp->sec = sec; tp->msec = msec; time_t tt = time(NULL); struct tm* gmt = gmtime(&tt); p0 = &cached_http_time[slot][0]; sprintf(p0, "%s, %02d %s %4d %02d:%02d:%02d GMT", week[gmt->tm_wday], gmt->tm_mday, months[gmt->tm_mon], gmt->tm_year + 1900, gmt->tm_hour, gmt->tm_min, gmt->tm_sec); struct tm* p = localtime(&tt); p->tm_mon++; p->tm_year += 1900; tp->gmtoff = get_timezone(p->tm_isdst); p1 = &cached_err_log_time[slot][0]; sprintf(p1, "%4d/%02d/%02d %02d:%02d:%02d", p->tm_year, p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec); p2 = &cached_http_log_time[slot][0]; sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", p->tm_mday, months[p->tm_mon - 1], p->tm_year, p->tm_hour, p->tm_min, p->tm_sec, tp->gmtoff < 0 ? '-' : '+', abs(tp->gmtoff / 60), abs(tp->gmtoff % 60)); _cached_time = tp; http_time = p0; err_log_time = p1; http_log_time = p2; }
Dateヘッダやアクセスログに出す時間は秒単位なので秒が変わらない間はキャッシュしてる値を使い回すという作戦。
abのように短時間にひたすらさばき続けないといけないケースで効果がある。
まあ実運用になるとどうなの?って感じもするけど。。。