ゆるゆる〜tech ver〜

勉強したこととかかく

mapっぽくなにか

先日気になったのでどうなのかなーって思って調べた話。(for Perl)

my @array = ( 1..1_000 );

この配列の値をハッシュのkeyにして扱いやすくしてあれこれしていく、っていうを割とやるのですが、 だいたい

my %map = map { $_ => 1 } @array;

とか

my %map;
foreach my $id ( @array ) {
    $map{$id} = 1;
}

とかってやってたのですが先日

my %map;
@map{@array} = ();

outout が \%map = { 1 => undef, 2 => undef, .... } こう書いた方が速いです、というコメントを見て、こんな書き方できるのかーって思ったのと 本当に速いんですか?って思ったので調べた。

#!/usr/bin/env perl
use strict;
use warnings;
use Time::HiRes qw(gettimeofday tv_interval);
my @array = ( 1..1_000 );
{
    my $t0 = [gettimeofday];
    my %map;
    @map{@array} = ();
    my $elapsed = tv_interval($t0);
    print '--@map{@array}--' . "\n";
    print $elapsed * 1000 . "\n";
}
{
    my $t0 = [gettimeofday];
    my %map = map { $_ => 1 } @array;
    my $elapsed = tv_interval($t0);
    print '--map--' . "\n";
    print $elapsed * 1000 . "\n";
}
{
    my $t0 = [gettimeofday];
    my %map;
    foreach my $id ( @array ) {
        $map{$id} = 1;
    }
    my $elapsed = tv_interval($t0);
    print '--foreach--' . "\n";
    print $elapsed * 1000 . "\n";
}
{
    my $t0 = [gettimeofday];
    my %map;
    for my $id ( @array ) {
        $map{$id} = 1;
    }
    my $elapsed = tv_interval($t0);
    print '--for--' . "\n";
    print $elapsed * 1000 . "\n";
}

1;

実行結果

1_000_000で実行

$perl sample.pl
--@map{@array}--
740.508
--map--
1199.097
--foreach--
639.542
--for--
650.275

10_000_000 で実行

$perl sample.pl 10_000_000
--@map{@array}--
11308.191
--map--
16796.802
--foreach--
9985.983
--for--
10101.491

※ foreachとforが定期的にどっちが速いのかわからなくなるのでまた調べた。 一応 perlsyn - perldoc.perl.org

The foreach keyword is actually a synonym for the for keyword, so you can use either

for と foreachはperldocで同義ですよって言われている。 foreachが速いって思ってたんだけどPHPとごっちゃになってるのかな。

[PHP]ループのメモリ使用量と処理速度を比較しました - Qiita

とにかく

foreach = for > @map{@array} > map

の順で速かったので mapより @map{@array} にしたほうが速かった。

ちなみに valueがundefになって速いなら

my %map;
foreach my $id ( @array ) {
    $map{$id} = undef;
}

にしたら速くなるのでは?と思ったけどそんなことはなかった。

まあけど、可読性がよくなるという理由以外にmap使わないようにしましょうって話ですね。

ワンライナーかっこいいという理由でmap使いがちでした/(^o^)\おわた

GCPで定期実行

GCPcron.yamlAPIを定期的に叩くって感じ。

なので、外部アクセスが定期的に動かしたい処理を入れたpathにアクセスがあると実行されてしまう。

それを回避するには、 cron.yaml からのアクセスにはヘッダーに下記の情報が含まれるので、それを利用する。

ドキュメントには

cron サービスからのリクエストには、次の HTTP ヘッダーも含まれます。

X-Appengine-Cron: true

とあるが、これは違うっぽい?

HTTP_X_APPENGINE_CRON: true

っぽい。 (けどまだちゃんと確認できてない)

Djangoでやってたので

def hoge(request)
    if not request.META.get('HTTP_X_APPENGINE_CRON') is None:
        ## 実行したい処理

みたいな感じだと動いた(^O^)/やった〜

ただ、cron.yamlgcloud app deploy cron.yaml, gcloud app deploy を打ったあとだとすぐは動かない...? ようで手動でcron動かすとずっと500エラーになってしまった。 一晩寝かせたら動いていて、なぞof謎だった。

参考

HerokuでRailsのtimezoneの設定

Herokuのtimezoneの設定

heroku config:add TZ=Asia/Tokyo
heroku run bash
Running bash on ⬢ yorakashi... up, run.3031 (Hobby)
~ $ date
Wed Apr 17 23:45:05 JST 2019

ここでJSTになっていることを確認

PostgreSQLのtimezone

herokuのDBにPSequelから接続する - ゆるゆる〜tech ver〜 こんな感じで PSequelから入って、Queryのところで

alter database your_database_name set timezone = 'Asia/Tokyo';
select current_timestamp;

で確認

config/application.rb

    config.time_zone = 'Tokyo'
    config.active_record.default_timezone = :local

scriptでreserved_on みたいな datetimeを設定してレコード突っ込んでたら、意図しない時間に表示されてあれ???ってなった。 config.active_record.default_timezone = :local がいなかった...しゅん....

Unity: Android用のPluginを作る Kotlin

はまったこと

ggってでてくる感じでいけるけど、Make Module 'hogehoge' すると

import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

がないよって怒られる。

cp /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes/classes.jar /Users/xxxx/AndroidStudioProjects/[APP_NAME]/[Plugin_Name]/libs/

にこぴーすればいける

Android Javaで書こうと思ったら

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //省略
    compile files('/Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes/classes.jar')
    compile files('/Users/UserName/Library/Android/sdk/platforms/android-26/android.jar')  /*Androidプラグインとして利用するため追加*/
}

この下の2行を足す。 compile files は書き方が古いみたいだけど、ちゃんとした書き方がわからなかった。

classes.jar の場所サイトに書いてあるのと違ってちょっとハマった。 ちなみに Unity 3.3f

そしたらMake Module できました!やったね!

そしたらxxxxx(plugin name)/build/outputs/aar ってディレクトリができてて、.aarができている。

参考

heroku run rake db:seedが反映されない

require "csv"

CSV.foreach('db/csv/hoge.csv') do |row|
 Member.create(:gender => row[1], :age => row[2], :name => "hoge", :status => 1)
end

みたいなスクリプトをかいて、 rake db:seed を実行するとローカルのDBには反映された。

けれど、 Rails5 heroku run rake db:seed を実行しても 何も反映されない。

なんともこの変更した差分を git push heroku master していないだけだった。

そういうところやぞ

ストアドプロシージャでさくっと100万レコード作る

クエリーチューニングするときにスクリプト使って入れるよりさくっと欲しいときに。。。

CREATE TABLE `test_table` (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `tester_id` int(10) UNSIGNED NOT NULL,
  `hoge_id` int(10) UNSIGNED NOT NULL,
  `fuga_id` int(10) UNSIGNED NOT NULL,
  `status` TINYINT(1)  NOT NULL DEFAULT 0 COMMENT '0: incactive, 1,: active',
  `created_on` int(10) unsigned NOT NULL,
  `updated_on` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

1回消しておく

drop procedure if exists doWhile;

作る

DELIMITER //
CREATE PROCEDURE doWhile()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE (i < 100) DO
    INSERT INTO test_table (tester_id, hoge_id,fuga_id, status, created_on ) VALUES (i, 29905, 119619, (CAST(RAND() * 2 AS UNSIGNED)), unix_timestamp());
     SET i = i+1;
END WHILE;
END;
// 

実行する

CALL doWhile();