query: %s

4 Way Technologies is one of the Leading Smart TV App Development Companies in the USA, UK & Australia which design & develops world-class applications for smart TV, Smart TV App Development, TV App Development etc. Our Smart TV Developer develops apps for Smart TV and also for other platforms including Android TV, Apple TV, LG TV, Roku TV etc applications for the leading clients. You can review some of our exciting work from here and you can also meet us in New Jersey state.

https://4waytechnologies.com/technology/smart-tv-app-development

image1.png

posted by 4waytechnologies 4waytechnologies on Mon 25 Feb 2019 at 07:46 with 0 comments

Get Top Apple TV Development services from 4 Way Technologies which works in the designing and development of Apple TV apps and we have top Apple TV Developer provide cutting edge services in the development of Apple TV applications and also in other development platforms be it TVOS Development, TVOS App Development, Apple TV App Development etc. Connect with us to develop your applications and you can also find us in Maryland state and other countries including the USA, UK & Australia.

https://4waytechnologies.com/technology/smart-tv-app-development/apple

image1.png

posted by 4waytechnologies 4waytechnologies on Mon 18 Feb 2019 at 10:17 with 0 comments

下図のような感じのディスプレイ作ろうとしてる人いないですかね。

FiberSweepDisplay.png

撮像用途では光ファイバスキャナの研究を見かけたのですが。

ディスプレイでも行けそうですよね

posted by genki genki on Tue 21 Mar 2017 at 16:00 with 0 comments

Xの原因だと思っていたものが、実はXの結果であった、という事は結構ありますね。前後即因果の誤謬に近いかな。虚偽の原因の誤謬の一種ですね。

posted by genki genki on Fri 3 Jun 2016 at 14:20 with 0 comments

例えば、String <-> NSAttributedString

ruby>>
@objc(S2ASTransformer) class
S2ASTransformer : NSValueTransformer {

override static	func
transformedValueClass() -> AnyClass {
	return NSAttributedString.self
}
override static	func
allowsReverseTransformation() -> Bool {
	return true
}
override func
transformedValue( p: AnyObject? ) -> AnyObject {
	if let w = p as? String { return NSAttributedString( string: w ) } else { return NSAttributedString() }
}
override func
reverseTransformedValue( p: AnyObject? ) -> AnyObject {
	if let w = p as? NSAttributedString { return w.string } else { return "" }
}

}

<<--

こんなの作ってこうやって登録

ruby>>
func
applicationDidFinishLaunching( p: NSNotification ) {
NSValueTransformer.setValueTransformer( S2ASTransformer(), forName: "S2ASTransformer" )
}

<<--

posted by Saturn Saturn on Sat 26 Mar 2016 at 15:56 with 0 comments

Though currently I am prefer to use CofferScript than Swift, I have thought that the defer of Swift2 is pretty cool. So I wrote a snippet that accomplishes the feature by using yield as like the manner of co is doing.

ruby>>
defer = (g) ->
deferred = []
go = (i) ->
{value,done} = do i.next
unless done
deferred.push value
go i
exit = ->
do f for f in deferred
process.removeListener 'exit', exit
process.on 'exit', exit
try go do g
catch then do exit

foo = (type) -> defer ->
console.log "#{type} 1"
yield -> console.log "#{type} deferred 1!"
yield -> console.log "#{type} deferred 2!"
console.log "#{type} 2"
if type == "exit" then do process.exit
else throw "throw"
console.log "3"

foo "throw"
foo "exit"

RESULTS

throw 1

throw 2

throw deferred 1!

throw deferred 2!

exit 1

exit 2

exit deferred 1!

exit deferred 2!

<<--

posted by genki genki on Sat 10 Oct 2015 at 00:25 with 0 comments

ということで、適当なセカンダリで重複を探して予め削除する必要が。
aggregateで探す例)
ruby>>
aggregate([
{:$group => {_id: {user_id:"$user_id", date:"$date"},
uniqueIds: {:$addToSet => "$_id"}, count:{:$sum => 1}}},
{:$match => {count: {:$gt => 1}}}],
allowDiskUse: true)
<<--

posted by genki genki on Fri 22 May 2015 at 02:26 with 0 comments

WiredTigerが非常に素晴らしいのですが、設定ファイルが

  1. /etc/mongod.conf
  2. /var/lib/mongodb/WiredTiger.basecfg
  3. /var/lib/mongodb/WiredTiger.config

のように沢山あって結構ややこしいです。

基本的には 1. はmongodbの初回起動時だけ有効で、3. が次回以降の再起動で反映されるものになります。
さらに、mongodbを動かしたままWiredTigerの設定だけ変更したい場合は、
mongoのコンソールから

js>>
db.adminCommand({setParameter:1, wiredTigerEngineRuntimeConfig:"c
ache_size=8G"})
<<--

のように修正できるようです。パラメータ名は 2. のファイルの中身が参考になります。
これによって内部的にはWT_CONNECTION::reconfigureが実行される模様。

修正したら、次回来起動した場合に備えて 3. も書き換えておくと良いでしょう。

posted by genki genki on Wed 13 May 2015 at 03:33 with 0 comments

たびたび見失ってGoogleで探すのに苦労するので道標的に。

posted by genki genki on Fri 8 May 2015 at 21:38 with 0 comments

ruby>>
// To use those functions below
// You need to import CommonCrypto.h in your bridging header.
// #import <CommonCrypto/CommonCrypto.h>

func
DataCryptedByAES( operation: CCOperation, p: NSData, key: NSData, _ options: CCOptions = CCOptions( kCCOptionPKCS7Padding ), _ iv: NSData? = nil ) -> ( CCCryptorStatus, NSData ) {
var wKeyLength = 0
if key.length < kCCKeySizeAES128 { assert( false ) }
else if key.length < kCCKeySizeAES192 { wKeyLength = kCCKeySizeAES128 }
else if key.length < kCCKeySizeAES256 { wKeyLength = kCCKeySizeAES192 }
else { wKeyLength = kCCKeySizeAES256 }

if iv != nil { assert( iv!.length == kCCBlockSizeAES128 ) }

var	wLength = UInt( ( ( p.length + kCCBlockSizeAES128 - 1 ) / kCCBlockSizeAES128 ) * kCCBlockSizeAES128 )
let	v = NSMutableData( length: Int( wLength ) )!
let	s: CCCryptorStatus = CCCrypt(
	operation
,	CCAlgorithm( kCCAlgorithmAES )
,	options
,	key.bytes
,	UInt( wKeyLength )
,	iv != nil ? iv!.bytes : nil
,	p.bytes
,	UInt( p.length )
,	v.mutableBytes
,	wLength
,	&wLength
)
v.length = Int( wLength )
return ( s, v )

}

func
DataEncryptedByAES( p: NSData, key: NSData, _ options: CCOptions = CCOptions( kCCOptionPKCS7Padding ), _ iv: NSData? = nil ) -> ( CCCryptorStatus, NSData ) {
return DataCryptedByAES( CCOperation( kCCEncrypt ), p, key, options, iv )
}

func
DataDecryptedByAES( p: NSData, key: NSData, _ options: CCOptions = CCOptions( kCCOptionPKCS7Padding ), _ iv: NSData? = nil ) -> ( CCCryptorStatus, NSData ) {
return DataCryptedByAES( CCOperation( kCCDecrypt ), p, key, options, iv )
}

func
DataCryptedByBlowfish( operation: CCOperation, p: NSData, key: NSData, _ options: CCOptions = CCOptions( kCCOptionPKCS7Padding ), _ iv: NSData? = nil ) -> ( CCCryptorStatus, NSData ) {
if iv != nil { assert( iv!.length == kCCBlockSizeBlowfish ) }

var	wLength = UInt( ( ( p.length + kCCBlockSizeBlowfish - 1 ) / kCCBlockSizeBlowfish ) * kCCBlockSizeBlowfish )
let	v = NSMutableData( length: Int( wLength ) )!
let	s: CCCryptorStatus = CCCrypt(
	operation
,	CCAlgorithm( kCCAlgorithmBlowfish )
,	options
,	key.bytes
,	UInt( key.length )
,	iv != nil ? iv!.bytes : nil
,	p.bytes
,	UInt( p.length )
,	v.mutableBytes
,	wLength
,	&wLength
)
v.length = Int( wLength )
return ( s, v )

}

func
DataEncryptedByBlowfish( p: NSData, key: NSData, _ options: CCOptions = CCOptions( kCCOptionPKCS7Padding ), _ iv: NSData? = nil ) -> ( CCCryptorStatus, NSData ) {
return DataCryptedByBlowfish( CCOperation( kCCEncrypt ), p, key, options, iv )
}

func
DataDecryptedByBlowfish( p: NSData, key: NSData, _ options: CCOptions = CCOptions( kCCOptionPKCS7Padding ), _ iv: NSData? = nil ) -> ( CCCryptorStatus, NSData ) {
return DataCryptedByBlowfish( CCOperation( kCCDecrypt ), p, key, options, iv )
}

//USAGE

func
UTF8Data( p: String ) -> NSData? {
return p.dataUsingEncoding( NSUTF8StringEncoding )
}

func
Usage() {
let wKey = UTF8Data( "teststring" )!
let wIV = UTF8Data( "12345678" )!
var ( s, data ) = DataEncryptedByBlowfish( UTF8Data( "testmessage" )!, wKey, CCOptions( kCCOptionPKCS7Padding ), wIV )
assert( Int( s ) == kCCSuccess )
( s, data ) = DataDecryptedByBlowfish( data, wKey, CCOptions( kCCOptionPKCS7Padding ), wIV )
assert( Int( s ) == kCCSuccess )
}

<<--

posted by Saturn Saturn on Thu 26 Mar 2015 at 08:46 with 0 comments

キーチェーンアクセス -> 証明書アシスタント -> 証明書を作成

OreOre.tiff

できた証明書を p12 で書き出し。

openssl pkcs12 -in OreOre.p12 -nodes -out OreOre.pem

でパスワードがついていない pem を作成。
この中に証明書も鍵も入っているので、tls.LoadX509KeyPair
の引数は両方とも "OreOre.pem" で大丈夫。

posted by Saturn Saturn on Wed 24 Dec 2014 at 22:17 with 0 comments

ruby>>
package main

import (
"net"
"sync"
"crypto/rand"
"crypto/tls"
"log"
"encoding/json"
)

func
main() {

cert, err := tls.LoadX509KeyPair( "OreOre.pem", "OreOre.pem" )
if err != nil { log.Fatalf( "LoadX509KeyPair:%v", err ) }
config := &tls.Config{
	Certificates: []tls.Certificate{ cert }, 
	ClientAuth: tls.VerifyClientCertIfGiven, 
	ServerName: "example.com",
	Rand:	rand.Reader,
}

connections := map[ net.Conn ] interface{} {}
mutex := sync.RWMutex{}

broadcaster := make( chan interface{} )
go func() {
	for {
		data, _ := json.Marshal( <- broadcaster )
		mutex.RLock()
		conns := connections
		mutex.RUnlock()
		for conn, _ := range conns { conn.Write( data ) }
	}
}()

listener, _ := tls.Listen( "tcp", ":6666", config )
defer listener.Close()
for {
	conn, _ := listener.Accept()
	mutex.Lock()
	connections[ conn ] = ""
	mutex.Unlock()
	go func() {
		decoder := json.NewDecoder( conn )
		for {
			var	w interface{}
			err := decoder.Decode( &w )
			if err != nil { break }
			broadcaster <- w 
		}
		mutex.Lock()
		delete( connections, conn )
		mutex.Unlock()
		conn.Close()
	}()
}

}
<<--

証明書がオレオレなので openssl で検証。

openssl s_client -tls1 -connect localhost:6666

posted by Saturn Saturn on Wed 24 Dec 2014 at 22:09 with 0 comments

ruby>>
package main

import (
"net"
"sync"
"encoding/json"
)

func
main() {

connections := map[ net.Conn ] interface{} {}
mutex := sync.RWMutex{}

broadcaster := make( chan interface{} )
go func() {
	for {
		data, _ := json.Marshal( <- broadcaster )
		mutex.RLock()
		conns := connections
		mutex.RUnlock()
		for conn, _ := range conns { conn.Write( data ) }
	}
}()

listener, _ := net.Listen( "tcp", ":6666" )
defer listener.Close()
for {
	conn, _ := listener.Accept()
	mutex.Lock()
	connections[ conn ] = ""
	mutex.Unlock()
	go func() {
		decoder := json.NewDecoder( conn )
		for {
			var	w interface{}
			err := decoder.Decode( &w )
			if err != nil { break }
			broadcaster <- w
		}
		mutex.Lock()
		delete( connections, conn )
		mutex.Unlock()
		conn.Close()
	}()
}

}
<<--

posted by Saturn Saturn on Wed 24 Dec 2014 at 22:07 with 0 comments

 RSpecで現在時刻に関連するテストをするときに、Rails4.1からはTimecopを使わなくても ActiveSupport::Testing::TimeHelpers の to_travel というメソッドを使って現在時刻を設定することができます。

 たとえば、下記のように現在時刻を返すメソッドがあるとします。

ruby>>
class Foo
def now
Time.now
end
end
<<--

 正しく現在時刻を返しているかのテストは下記のように書けます。

ruby>>
travel_to Time.new(2014, 11, 24, 9, 30, 0) do
foo = Foo.new
expect(foo.now).to eq(Time.new(2014, 11, 24, 9, 30, 0))
end
<<--

 travel_toで現在時刻を設定しているので、expectで評価するときに決まった時間を書いて比較できます。

 ですがもしnowメソッドでDateTime.nowを返していると、to_travelでは対応できません。

ruby>>
class Foo
def now
DateTime.now # <- to_travelで設定した時間ではなく現在時刻が返る
end
end
<<--

 その場合にはやはりTimecopを使う必要があります。Gemfileには下記のようにgemを追加。

ruby>>
group :test do
gem 'timecop'
end
<<--

 テストは下記のように記述します。

ruby>>
Timecop.freeze(Time.new(2014, 11, 24, 9, 30, 0)) do
foo = Foo.new
expect(foo.now).to eq(Time.new(2014, 11, 24, 9, 30, 0))
end
<<--

 travel_to が対応しているのは Time.now と Date.today のみのようです。

 travel_to(date_or_time, &block)

 rails4.1からのtravel_toをrspecで使う

posted by akanuma akanuma on Tue 25 Nov 2014 at 00:03 with 0 comments

環境変数によってRailsアプリの動作を切り替えたいことがあって、

nginx + Passenger で動かしているRailsアプリに環境変数を渡す方法を調べました。

nginx の起動スクリプト(/etc/init.d/nginx)に書いても、

/etc/default/nginx に書いてもうまくいかなかったのですが、

nginx の設定ファイルの location ブロックで

passenger_set_cgi_param で設定することで環境変数が設定できます。

sh>>
passenger_set_cgi_param HOGE fuga;
<<--

これでRailsアプリの中で ENV['HOGE'] で "fuga" という値が取得できるように
なります。

参考ページ

16.3.5. Phusion Passengerが提供するアプリケーション

8.6.1. passenger_set_cgi_param

posted by akanuma akanuma on Sat 22 Nov 2014 at 14:14 with 0 comments
Rails4で入力フォームから日時を選択できるように datetimepicker を使ったのですがちゃんと動くまでに軽くはまったのでメモ。 [bootstrap3-datetimepicker-rails](https://github.com/TrevorS/bootstrap3-datetimepicker-rails) まずはGemfileに下記エントリを追加して bundle install ruby>> gem 'momentjs-rails' gem 'bootstrap3-datetimepicker-rails' <<-- moment と datetimepicker のJavaScriptファイルを読み込むための設定を追加します。 私は coffeescript を使っているので application.js.coffee に下記エントリ を追加します。 bootstrapの設定が入っていない場合はあわせて追加します。 js>> #= require bootstrap #= require moment #= require bootstrap-datetimepicker <<-- 続いてstylesheetの設定も追加します。 私の場合は scss を使っているので、application.css.scss に下記を追加。 ちなみに順番もこの通りじゃないとちゃんと動きません。 css>> @import "bootstrap-sprockets"; @import "bootstrap"; @import "bootstrap-datetimepicker"; <<-- ここまででひとまずの下準備は終了なので、実際にdatetimepickerを適用したい部分の作業をします。 今回の対象のView部分は下記のような感じです。 html>>
<%= f.text_field :start_datetime, value: @user.start_datetime, class: "form-control", id: "user_start_datetime" %>
<<-- f.text_field で出力される input タグに対して datetimepicker() メソッドを 実行します。 下記内容でcoffeescriptのファイルを別途作成して読み込みます。 js>> $ -> $('#user_start_datetime').datetimepicker() <<-- これで入力ボックスを選択した時に日時選択用のポップアップが表示されるようになります。 また、日付のフォーマットのデフォルトは MM/DD/YYYY hh:mm A/PM なので、日本の形式に変更します。 inputタグに data-date-format 属性で指定するのですが、rails の text_field タグでは追加の属性を指定できないため、先ほどのcoffeescriptを変更して動的に属性を追加します。 js>> $ -> date_format = {'data-date-format': 'YYYY/MM/DD HH:mm'} $('#user_start_datetime').attr(date_format) $('#user_start_datetime').datetimepicker() <<-- これで日付フォーマットが変更されます。 今回は一番シンプルな形で datetimepicker を使いましたが、オプションの指定で表示形式などは色々変更できますので、試してみてもらえると良いかと思います。 参考ページ [http://eonasdan.github.io/bootstrap-datetimepicker/](http://eonasdan.github.io/bootstrap-datetimepicker/)
posted by akanuma akanuma on Sat 22 Nov 2014 at 14:03 with 0 comments

 VagrantでUbuntu環境を立ち上げようとするとChefでのProvision中にabortするというのが発生していてしばらく原因が分からなかったのですが、名前解決できなかったのが問題だったようです。

 私のケースでは config.vm.box に chef/ubuntu-14.04 を指定して、 chef.run_list では apt, sqlite, redisio などの cookbook を指定した状態で vagrant up すると、下記のようにProvision中にabortしていました。

sh>>
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'chef/ubuntu-14.04'...
==> default: Matching MAC address for NAT networking...
〜〜〜中略〜〜〜
==> default: [2014-11-16T11:51:03+00:00] WARN: Cloning resource attributes for package[tar] from prior resource (CHEF-3694)
==> default: [2014-11-16T11:51:03+00:00] WARN: Previous package[tar]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/redisio/recipes/default.rb:23:in block in from_file' ==> default: [2014-11-16T11:51:03+00:00] WARN: Current package[tar]: /tmp/vagrant-chef-3/chef-solo-1/cookbooks/ruby_build/recipes/default.rb:34:in block in from_file'
<<--

 このときVMの状態は abort になります。

sh>>
$ vagrant status
Current machine states:

default aborted (virtualbox)
<<--

 provisionなしでの起動はできるので、試しに再度 vagrant up したあとに vagrant ssh してUbuntuにログインし、 sudo apt-get update してみました。

sh>>
vagrant@vagrant:~$ sudo apt-get update
0% [Connecting to us.archive.ubuntu.com] [Connecting to security.ubuntu.com]Connection to 127.0.0.1 closed by remote host.
Connection to 127.0.0.1 closed.
<<--

 securiy.ubuntu.com に接続しようとしているときに終了してしまっているようです。このときVMはまたaborted状態になります。VM上からインターネットへのアクセスはできていたのですが、どうも名前解決あたりが怪しそうだと思って調べていたところ、下記記事を発見。

Virtual Box ゲストから外部ネットワークにつながらない(解決済み)

 上記サイトで紹介されている通り、config.vm.provider の設定にNAT接続時のDNSの挙動に関連する、natdnshostresolver1、natdnsproxy1 を追加します。

ruby>>
config.vm.provider :virtualbox do |vb|
vb.gui = false
vb.customize ['modifyvm', :id, '--memory', '1024']
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
end
<<--

 この設定を追加することで、VM上での名前解決要求がホストマシンのDNSサーバによって行われるようになります。

9.11.5. Enabling DNS proxy in NAT mode

9.11.6. Using the host's resolver as a DNS proxy in NAT mode

 上記設定を追加して一旦 vagrant destroy したあとに vagrant up し直したところ、無事Provisionが完了するようになりました。

posted by akanuma akanuma on Sun 16 Nov 2014 at 21:28 with 0 comments

UITextField の場合

ruby>>
  → UITextFieldTextDidBeginEditingNotification
    UIKeyboardWillChangeFrameNotification
    UIKeyboardWillShowNotification
    UIKeyboardDidChangeFrameNotification
    UIKeyboardDidShowNotification

<<--

UITextView の場合

 
ruby>>
   UIKeyboardWillChangeFrameNotification
    UIKeyboardWillShowNotification
  → UITextViewTextDidBeginEditingNotification
    UIKeyboardDidChangeFrameNotification
    UIKeyboardDidShowNotification

<<--

iOS7, iOS8 両方

posted by Saturn Saturn on Thu 25 Sep 2014 at 18:06 with 0 comments

The code below is example which toggles view which covers status bar.

ruby>>
import UIKit

class
ViewController: UIViewController {

var	uWindow:	UIWindow!

@IBAction	func
Do( AnyObject! ) {
	if uWindow {
		uWindow = nil
	} else {
		uWindow = UIWindow( frame: UIApplication.sharedApplication().statusBarFrame )
		uWindow.backgroundColor = UIColor( white:0, alpha:0.5 )
		uWindow.windowLevel = UIWindowLevelStatusBar + 1
		uWindow.hidden = false;
	}
}

}

<<--

posted by Saturn Saturn on Mon 4 Aug 2014 at 18:25 with 0 comments

そろそろDroongaをちゃんと使ってみようと思ってますが、
開きっぱなしのブラウザのタブを削減するために書き出しておきます。

posted by genki genki on Wed 30 Jul 2014 at 17:34 with 0 comments

ライブラリの内部から素のRuntimeErrorが飛んでくると対処に困りますね。
適当な例外クラスを用意してほしいものですが、とりあえず以下のような関数を定義することで、特定のメッセージの場合だけrescueできます。

ruby>>
def RuntimeError(message)
($!.is_a?(RuntimeError) and $!.message == message) ? RuntimeError : Class
end

begin

do something

rescue RuntimeError('connection closed by server') => e

...

end
<<--

posted by genki genki on Tue 29 Jul 2014 at 10:58 with 0 comments

jQueryで append すると、追加したDOM中のscript タグが実行されます。

js>>
$('#target').append(what);
<<--

script タグを実行せずに append したい場合、あらかじめ
script タグを取り除いておけば ok

js>>
what.find('script').remove();
$('#target').append(what);
<<--

posted by genki genki on Sun 6 Jul 2014 at 18:05 with 0 comments

ActiveRecordのmigrationで change と up/down を同居させるには、
以下のように書けば良いようです。

ruby>>
class DoSomething < ActiveRecord::Migration
def change
#change
end

def migrate(direction)
super
case direction
when :up
# up
when :down
# down
end
end
end
<<--

posted by genki genki on Sun 15 Jun 2014 at 10:00 with 0 comments

docker pull が途中で失敗した場合などに、
docker run しようとすると掲題のようなエラーメッセージがでて
応答がなくなることがあります。

pre>>
Repository ubuntu already being pulled by another client. Waiting.
<<--

こんな場合には、

pre>>
boot2docker restart
<<--

してからもう一度 docker pull を実行して正常に完了させればokのようです。

posted by genki genki on Mon 12 May 2014 at 01:36 with 0 comments

まずはGithubからcloneしてくる。

pre>>
git clone https://github.com/Homebrew/linuxbrew.git ~/.linuxbrew
<<--

あとは .zshrc などで

sh>>
export PATH="$HOME/.linuxbrew/bin:$PATH"
export LD_LIBRARY_PATH="$HOME/.linuxbrew/lib:$LD_LIBRARY_PATH"
<<--

以上で完了。使い方は homebrew とだいたい同じ

posted by genki genki on Sun 11 May 2014 at 20:40 with 0 comments

上部のバーのサイズ:69

〜 編集領域最上部:38

〜 編集領域最下部:320

〜 下部のバー上部:427-38-320

添付の画像を frame.origin.y == 69 で cameraOverlayView にセットすればフィットする。

Circle@2x.png

posted by Saturn Saturn on Wed 7 May 2014 at 19:53 with 0 comments
UIView のインスタンスの tag に値を設定した後、removeFromSuperview すると値は 0 にリセットされる(;;)
posted by Saturn Saturn on Mon 28 Apr 2014 at 20:23 with 0 comments

ユーザーが設定でロケーションの設定をいぢると、

didFailWithError

が呼ばれる。Grant したときでさえも code = 0 で呼ばれる!

ユーザーが設定でロケーションの許可を与えなかったとき、だからといってstopUptatingLocation を呼んでしまうと、その後許可を与えたことがわからなくなる。ネットの例はこれが多いので注意。

ruby>>
- (void)
locationManager:(CLLocationManager*)pLM
didFailWithError:(NSError*)pError
{ assert( [ pError.domain isEqual:kCLErrorDomain ] );
switch ( pError.code )
{
case 0: // User grant permission to access Location.
break;
case 1: // User change permittion to access Location to disabled, needs to uLocation be nil.
default: // But don't stop update location, you can't come back when user granted permission to access Location.
uLocation = nil;
break;
}
}
<<--

posted by Saturn Saturn on Mon 14 Apr 2014 at 17:44 with 0 comments

I recommend to use SoundFlower, the great audio routing program.

When using modules in AVFoundation, sound environment needs to be configured properly both input and output.
But MacPro2013 doesn't have internal microphone so it cannot be configured properly and when playing sound with AVAudioPlayer, errors like below will appear in console.

ruby>>
2014-04-09 11:50:47.717 XXXX[2897:60b] 11:50:47.717 ERROR: 398: error -66680
2014-04-09 11:50:47.717 XXXX[2897:60b] 11:50:47.717 ERROR: 398: error -66680
2014-04-09 11:50:47.717 XXXX[2897:60b] 11:50:47.717 ERROR: >aq> 1605: failed (-66680); will stop (11025/0 frames)

<<--

Because I don't have any microphones around me, I cannot plug it into my MacPro. I don't like to plug my earphone instead of plugging microphone.
There was another choice. Soundflower, the great software for routing audio. Installing this software and selecting SoundFlower(2ch) in Setting/Sound/Input solved this problem.

posted by Saturn Saturn on Wed 9 Apr 2014 at 12:26 with 0 comments

カリスマトリマーの友達がドメインをエクスパイアしちゃったからとヘルプ依頼。

一週間前から HP が見えなくなっているらしい。

他人に依頼していたので、コンタクト情報なし、リセーラーもわからない。

whois で見ると、レジストラはメルボルンIT。あれ、ここよく見るな。

連絡先のアドレスがなんと、XXXX@hotmail.com、これじゃ連絡こないわな(笑)

というわけでメルボルンIT の HP に行ってドメインを検索すると、小さく Renew のリンクが。

飛んでみると復活できそう。

メアドをなんとかしなくちゃいけないので相談しなくちゃ、と思いサポートコミュニティを見ると、Renewal の相談の嵐。

エクスパイアさせちゃうのは世界的なブームなのか(笑)というわけで早速投稿、朝一で返事がきた。

http://community.melbourneit.com.au/t5/Domain-Hosting/Domain-Renewal/m-p/11241

こういうサポートはほんとにありがたい。で、

https://www.melbourneit.com.au/document.php?handle=regkeyrecovery

このページからフォームをダウンロードして、ファックスかメールすればいいらしい。

あと、証人も用意する必要があるようだ。今夜に続く。。。かも

4/12 無事解決、よかった!。http://www.soup-spoon.com

posted by Saturn Saturn on Tue 8 Apr 2014 at 13:21 with 0 comments

With optimization level other than NONE,

[ UINib nibWithNibName:... ]

and

[ NSBundle.mainBundle loadNibNamed:... ]

return nil when custom view class is instantiated only in the nib file.

In this case, there needs to be dummy instantiation code somewhere reachable or compile with optimization level NONE.

ugly...

posted by Saturn Saturn on Tue 8 Apr 2014 at 05:58 with 0 comments

iPhone 5 Retina の解像度で画面一杯の画像を左に1ドットずらす事を考える

つまり 320 x 568 x 4 X 4 = 2908160 バイト数分のコピー

ruby>>
for/memmove 機種 Debug Release (nano sec)
int32 for forward 5 7798625 3169792
int32 for reverse 5 6819542 2541750
float for forward 5 8200625 2440875
float for reverse 5 5783625 2477167
int32 mem forward 5 1105375 1394833
int32 mem reverse 5 894833 1158125
float mem forward 5 1085958 1128250
float mem reverse 5 896542 946042

int32 for forward 5s 4817875 943250
int32 for reverse 5s 4419667 976417
float for forward 5s 4793042 893958
float for reverse 5s 4415625 934625
int32 mem forward 5s 593083 628042
int32 mem reverse 5s 644542 582750
float mem forward 5s 565583 605958
float mem reverse 5s 561875 594792

<<--

ちなみに Accelerate Framework の vDSP_vsaddX で0を足すという強引な手でやると、以下のような結果。(オーバーラップしているときは使える保証がないので参考までに)
5s の Accelerate が何故かすごく早くなっていて、OpenGL を使ったときのような発熱がある。GPU ベースに書き直したのか?

ruby>>
int32 DSP reverse 5 1764667 2197000
int32 DSP reverse 5s 329292 393375
float DSP reverse 5 1083958 1291875
float DSP reverse 5s 325875 421125

<<--

ソース

ruby>>
inline void
SpeedTest()
{
// Normal
{ int32_t wNum = 320 * 568 * 4;
int32_t* w = new int32_t[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
for ( int32_t i = 0; i < wNum; i++ ) w[ i ] = w[ i + 1 ];
NSLog( @"Int32 Forward:%zd", wTimer.Nano() );
for ( size_t i = 0; i < wNum; i++ ) assert( w[ i ] == i + 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
int32_t* w = new int32_t[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
int32_t wCounter = wNum;
while ( wCounter-- ) w[ wCounter + 1 ] = w[ wCounter ];
NSLog( @"Int32 Reverse:%zd", wTimer.Nano() );
for ( size_t i = 1; i <= wNum; i++ ) assert( w[ i ] == i - 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
float* w = new float[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
for ( int32_t i = 0; i < wNum; i++ ) w[ i ] = w[ i + 1 ];
NSLog( @"Float Forward:%zd", wTimer.Nano() );
for ( size_t i = 0; i < wNum; i++ ) assert( w[ i ] == i + 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
float* w = new float[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
int32_t wCounter = wNum;
while ( wCounter-- ) w[ wCounter + 1 ] = w[ wCounter ];
NSLog( @"Float Reverse:%zd", wTimer.Nano() );
for ( size_t i = 1; i <= wNum; i++ ) assert( w[ i ] == i - 1 );
delete[] w;
}
// Memmove
{ int32_t wNum = 320 * 568 * 4;
int32_t* w = new int32_t[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
memmove( w, w + 1, wNum * 4 );
NSLog( @"Int32 Memmove Forward:%zd", wTimer.Nano() );
for ( size_t i = 0; i < wNum; i++ ) assert( w[ i ] == i + 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
int32_t* w = new int32_t[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
memmove( w + 1, w, wNum * 4 );
NSLog( @"Int32 Memmove Reverse:%zd", wTimer.Nano() );
for ( size_t i = 1; i <= wNum; i++ ) assert( w[ i ] == i - 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
float* w = new float[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
memmove( w, w + 1, wNum * 4 );
NSLog( @"Float Memmove Forward:%zd", wTimer.Nano() );
for ( size_t i = 0; i < wNum; i++ ) assert( w[ i ] == i + 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
float* w = new float[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
memmove( w + 1, w, wNum * 4 );
NSLog( @"Float Memmove Reverse:%zd", wTimer.Nano() );
for ( size_t i = 1; i <= wNum; i++ ) assert( w[ i ] == i - 1 );
delete[] w;
}
// DSP
{ int32_t wNum = 320 * 568 * 4;
int* w = new int[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
int wZero = 0;
vDSP_vsaddi( w + 1, 1, &wZero, w, 1, wNum );
NSLog( @"Int32 vDSP_vsaddi Rev:%zd", wTimer.Nano() );
for ( size_t i = 0; i < wNum; i++ ) assert( w[ i ] == i + 1 );
delete[] w;
}
{ int32_t wNum = 320 * 568 * 4;
float* w = new float[ wNum + 1 ];
for ( int32_t i = 0; i <= wNum; i++ ) w[ i ] = i;
Timer wTimer;
float wZero = 0;
vDSP_vsadd( w + 1, 1, &wZero, w, 1, wNum );
NSLog( @"Float vDSP_vsadd Rev:%zd", wTimer.Nano() );
for ( size_t i = 0; i < wNum; i++ ) assert( w[ i ] == i + 1 );
delete[] w;
}
}

<<--

posted by Saturn Saturn on Tue 8 Apr 2014 at 05:46 with 0 comments

設定ー>プライバシーー>連絡帳ー>リクエストしたアプリ

で変更できる。変更すると、リクエストしたアプリは SIGKILL で殺される。
不許可方向は当然だが、なんと許可方向でも殺される。
なので、アプリ内でフォアにきたとき

ruby>>
ABAddressBookRequestAccessWithCompletion

<<--
で再リクエストするようなコードは意味がない。アプリの起動時のみでいい。

posted by Saturn Saturn on Tue 8 Apr 2014 at 05:45 with 0 comments
posted by genki genki on Sat 5 Apr 2014 at 23:31 with 0 comments

以下のようにすればok。

pre>>
ffmpeg -i infile -t duration -ss from outfile
<<--

  • infile 入力ファイル名
  • duration 秒数
  • from 開始時刻(秒)
  • outfile 出力ファイル名
posted by genki genki on Wed 26 Feb 2014 at 12:37 with 0 comments

pre>>
use local
db.dropDatabase()
<<--

して

pre>>

service mongodb restart

<<--

posted by genki genki on Fri 24 Jan 2014 at 17:28 with 0 comments

こちらでは数年ぶりの更新ですね。

個人サイトは http://ysakaki.com/ 仕事では日本最大のパンケーキ専門サイト http://pancake.30min.jp/ を担当したり個人で 原宿パンケーキ速報 をやったりしています。

Mitaka.rbについては私の転職、転居に伴い休止しています。(が、pgcafeという受け皿コミュニティがあるからいいよね?と思っています)

posted by ysakaki ysakaki on Wed 8 Jan 2014 at 18:22 with 0 comments
正方行列 が冪零であるとは、ある整数 に対して (零行列)が成り立つことをいう。 が同じ型の冪零行列で を満たすとき、次を示せ。 (1)  は冪零 (2)  は冪零
posted by lvs lvs on Thu 26 Dec 2013 at 20:02 with 0 comments

 Passenger + Nginx でアプリケーションを起動しようとしたときに、下記のようなエラーが出ました。

sh>>
git://github.com/nzifnab/msgpack-rails.git (at master) is not checked out. Please run bundle install (Bundler::GitError)
<<--

 もちろん bundle install は実行済みです。msgpack-rails を使用するために、Gemfile に下記のような記述をしてあるのですが、色々調べたところ、Passenger が git からインストールした gem を認識してくれないようです。

ruby>>
gem 'msgpack-rails', :git => 'git://github.com/nzifnab/msgpack-rails.git'
<<--

 bundle install --deployment で解決するという情報も見つけたのですが、これは vendor ディレクトリにgemを持ってくるため結構な時間がかかります。デプロイでは世代管理していて、デプロイ時に新しいディレクトリを作成してデプロイしているので、開発環境のサーバへデプロイするたびに時間がかかるのはちょっと困るので他の方法を探したところ、bundle package
でOKという情報を見つけました。これはgemのキャッシュを vendor ディレクトリに持つもので、すぐに終わります。ただオプションで --all を指定しないと git 経由のgemをキャッシュしてくれないようです。

sh>>
bundle package --all
<<--

とすることで、git からの gem も見つけてくれるようになりました。

(参考サイト)deploying rails3 apps with bundler and phusion passenger: .bundle dir not found

posted by akanuma akanuma on Wed 25 Dec 2013 at 06:01 with 0 comments

 今まではネイティブのクライアントへJsonでレスポンスを返していたのですが、新しいサービスを開発する際に、レスポンスをMessagePackにしてはどうかとクライアントサイドから提案があったので検証してみました。

 ちなみにリクエストまでMessagePackにすると、リクエスト内容が簡単に参照できなくなってデバッグや問い合わせ時の調査が大変ということで、今回はレスポンスのみに使う想定です。

検証用アプリ


 構成は下記の通りです。

  • Nginx
  • Passenger
  • Ruby2.0
  • Rails4

 今回の検証はJson圧縮とMessagePack圧縮の比較です。アプリはRails4で実装します。また、JsonはデフォルトのJSONクラスよりもoj(Optimized JSON)が早いということなのでそちらを使用しています。MessagePackの方はMsgpackRailsを使います。Gemfileには下記を追加します。

(参考) JSONの替わりに使ったOJが速い
(参考) MsgpackRails

ruby>>
gem 'oj'
gem 'msgpack-rails', :git => 'git://github.com/nzifnab/msgpack-rails.git'
<<--

 Controllerは下記のように実装しました。

ruby>>
class StaticPagesController < ApplicationController

require 'oj'

after_action :testcompress

respond_to :json, :mpac

SERIALIZE_TEST_RESPONSE = {(省略)}

def serialize_test
respond_to do |format|
format.json { render :json => SERIALIZE_TEST_RESPONSE }
format.mpac { render :text => SERIALIZE_TEST_RESPONSE.to_msgpack, :content_type => 'application/x-mpac' }
end
end

def testcompress
response.body = ActiveSupport::Gzip.compress(response.body)
end

end
<<--

  • oj が追加されていると、MultiJSONによって自動的に oj が選択されるようです。
  • シリアライズするHashデータを SERIALIZE_TEST_RESPONSE として定義しておきます。
  • 処理内容としてはテスト用のデータをシリアライズして返すだけです。
  • また、今回はシリアライズ+圧縮を試すのですが、Rails側で圧縮した場合と、Nginxで圧縮した場合も比較してみます。Rails側で圧縮する場合の処理を testcompress メソッドに定義しておいて、after_action で gzip 処理を行います。Nginx側で圧縮する場合は after_action をコメントアウトします。

 検証方法としては、JMeterサーバを3つ用意して、100スレッドから上記APIへかけられるだけ負荷をかけてみるというやり方です。Nginxで圧縮するケースではHTTPヘッダマネージャでAccept-Encodingヘッダを設定する必要があります。また、Nginxの設定ファイルで下記の設定を有効にします。

sh>>
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/x-mpac;
<<--

 デフォルトでは application/x-mpac 以外が設定された状態でコメントアウトされていますので、コメントアウトを解除して application/x-mpac を追加してあります。

検証結果


検証結果は下記の通りです。

|caption=検証結果
|
|種別,圧縮,サンプル数,平均,中央値,90%LINE,最小値,最大値,スループット,KB/sec
|
|Json,Rails,48626,1816,1805,2002,25,2258,158.57,306.30
|MessagePack,Rails,271372,317,321,356,5,533,889.05,1701.66
|Json,Nginx,48824,1785,1775,1988,27,2206,159.11,393.07
|MessagePack,Nginx,333783,249,248,279,4,466,1093.61,2395.42
|MessagePack,非圧縮,346175,246,246,271,6,610,1134.33,19178.19

 Jsonの場合はCPUは常に振り切っている状態でしたが、MessagePackではCPUに余裕がありました。
 テスト結果のスループットとしてはMessagePack非圧縮のケースが一番速かったのですが、MessagePackのNginxでの圧縮の場合と大きな差はなく、実際のケースでは転送するデータ量を少なくすることによるメリットも大きいので、今回はMessagePackのNginx圧縮パターンを採用することにしました。

posted by akanuma akanuma on Sat 21 Dec 2013 at 19:00 with 0 comments

 仕事で新しいサービスのDBを何にするか検討していて、MongoDBと同じような使い方ができてサーバコストが抑えられるものがないか探していたときにCouchbaseのことを思い出してハンズオンセミナーなど受けてきました。結局Couchbaseは使わないことにしたのですが、主にMongoDBと比べてどうだったかといったあたりを書いておきます。

Couchbaseについてざっくりと


 まずCouchbaseがどういったものかをざっくり説明しておくと、MongoDBと同じようなドキュメント指向のNoSQL製品で、JSONデータを格納します。
 売りにしている特徴としては下記のような点が挙げられています。

  • 容易なスケーラビリティ
  • 安定したハイパフォーマンス
  • 24時間365日安定稼働
  • 柔軟なデータモデル

MongoDBと似ているところ


 また、下記のような思想はMongoDBと共通しています。

  • データは全部メモリに載せる
  • パフォーマンス出すにはサーバを追加する(スケールアウト)

 データが100GBあれば、masterノードのメモリの合計がそれ以上になるようにしましょう、という点では両者とも同じ思想で、サーバスペック的にもCPUよりもメモリを多く積んだサーバを必要とします。

比較して気になったところなど


 逆にMongoDBと比較して違う点で気になったところ等は下記のようなところです。

|caption=MongoDB/Couchbase比較
|
|項目,MongoDB,Couchbase
|
|レプリケーション,master-slaveレプリケーション,master-masterレプリケーション
|ノード追加,コマンドで設定変更,Webの管理画面から操作可能
|自動Failover,台数制限なし,同時に一台まで
|クエリ,SQLライクな柔軟なクエリ,MapReduceのみ
|ドキュメント削除時,ドキュメント削除時にすべて消える,メタデータが残ってしまう
|商用版と無償版,違いはサポートの有無,商用版がベースなのでバージョンアップなどもまず商用版から

 それぞれ簡単に説明していきます。

  • master-masterレプリケーション

    MongoDBではレプリケーションの構成はmaster-slaveになりますので、masterノードのレプリカはslaveサーバが保持します。なのでシャーディング構成をとっている場合で1レプリカセット3台で構成している場合は、1シャード増やす場合には1レプリカセット追加ということになって3ノード増やす必要があります。これに対してCouchbaseはmaster-masterレプリケーションなので、あるmasterノードのレプリカは他のmasterノードが保持します。なので1シャード追加する場合にも1ノード増やすだけでOKです。masterが他のmasterのレプリカを持つ分、1ノードあたりのデータ量はMongoDBと比べると多くなりますが、レプリカデータは普段は非Activeになっていてアクセスされないので、その分のメモリは足りていなくても運用できるとのことでした。(実際の動作検証はしてません。。)

  • 管理画面からノード追加

    MongoDBではクラスタへノードを追加する場合、コマンドラインから操作する必要がありますが、CouchbaseではWebの管理画面から操作することができます。追加後のリバランスもそのまま管理画面から実行可能で、データ量が増えてもリバランスの所要時間はあまり変わらないとのことです。また、Mongoではシャードキーを自分で設定しますが、Couchbaseでは自動で振り分けが行われるので、データの内容から置かれているサーバを特定することはできません。リバランス処理の負荷はやはり高いので、すでに負荷でいっぱいいっぱいの状態のクラスタでノード追加、リバランスを行うのはつらいものがあります。

  • 自動Failoverは一台まで

    MongoDBではレプリケーションがmaster-slave構成ということもあり、Failoverは同時に何シャードで起こっても大丈夫ですが、Couchbaseでは自動Failoverは1ノードまでなので、最初の1ノードを復旧する前にもう一台落ちた場合には、クラスタが停止します。管理画面から手動でFailoverさせることは可能です。

  • クエリはMapReduceのみ

    今回Couchbaseの採用を見送った最大の理由はこれなのですが、MongoDBではSQLライクな柔軟なクエリが使用できるのに対して、CouchbaseではクエリはすべてMapReduceで行う必要があります。前もってMapReduceの処理を定義しておき、アプリケーションなどからはどのMapReduce処理かを指定して結果を参照します。開発時の効率を考えるとすべての処理をMapReduceで書くのはつらいものがあるので今回は見送りました。来年出るバージョン3.0ではSQLライクなクエリであるN1QL(ニッケル)が実装されるそうですので、期待したいところです。

  • ドキュメントを消してもメタデータが残る

    Couchbaseではドキュメントを消した場合にもドキュメントのメタデータは消されずに残ってしまうので、容量を圧迫します。この残ったメタデータを削除する処理の実行頻度を管理画面から指定できるのですが、削除処理は負荷が高いようなので、運用時にはこういった点も考慮する必要があります。

  • 商用版ありき

    OSSには元々オープンソースとして始まったものに商用のサポートなどがつくケースが多いですが、Couchbaseは元々商用製品として始まったもののソースを公開している形になります。なのであくまでメインは商用版で、バージョンアップやパッチの公開等もまず商用版に対して行われ、Couchbaseのエンジニアの手が空いたときにOSS版がメンテナンスされることになります。現状バージョンアップについては商用版の半年遅れぐらいでOSS版が追随しているようですが、今後はさらに間隔が開いたり、機能やデータ容量の制限がかかってくることもあるかもしれません。無償で利用できるものを探している場合はこの辺りがネックになりそうです。現在の商用版の最新バージョンは2.2ですが、OSS版はまだ2.1です。次のバージョンの3.0はOSSではいつ公開されるのか。。


 今回は実際に性能の検証等を行うまでに使わないという判断をしてしまいましたが、いくつか公開されているベンチマークではCouchbaseがMongoDBなどより良い結果を出しているものもあるので、N1QLが利用できるようになったらパフォーマンス検証等行ってみたいと思います。ただ無償版の状況を考えるとなかなか難しいかもしれませんが。。

posted by akanuma akanuma on Tue 17 Dec 2013 at 06:21 with 0 comments

 Ruby on Rails で普通にプロジェクトを作成すると sqlite3 が使われるようになっていますが、mysql を使用するにはプロジェクト作成時に -d オプションで mysql を指定します。

sh>>
$ rails new turntable_test -d mysql
create
create README.rdoc
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/javascripts/application.js
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/views/layouts/application.html.erb
create app/assets/images/.keep
create app/mailers/.keep
create app/models/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
create bin
create bin/bundle
create bin/rails
create bin/rake
create config
create config/routes.rb
create config/application.rb
create config/environment.rb
create config/environments
create config/environments/development.rb
create config/environments/production.rb
create config/environments/test.rb
create config/initializers
create config/initializers/backtrace_silencers.rb
create config/initializers/filter_parameter_logging.rb
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/initializers/secret_token.rb
create config/initializers/session_store.rb
create config/initializers/wrap_parameters.rb
create config/locales
create config/locales/en.yml
create config/boot.rb
create config/database.yml
create db
create db/seeds.rb
create lib
create lib/tasks
create lib/tasks/.keep
create lib/assets
create lib/assets/.keep
create log
create log/.keep
create public
create public/404.html
create public/422.html
create public/500.html
create public/favicon.ico
create public/robots.txt
create test/fixtures
create test/fixtures/.keep
create test/controllers
create test/controllers/.keep
create test/mailers
create test/mailers/.keep
create test/models
create test/models/.keep
create test/helpers
create test/helpers/.keep
create test/integration
create test/integration/.keep
create test/test_helper.rb
create tmp/cache
create tmp/cache/assets
create vendor/assets/javascripts
create vendor/assets/javascripts/.keep
create vendor/assets/stylesheets
create vendor/assets/stylesheets/.keep
run bundle install
Enter your password to install the bundled RubyGems to your system:
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Using rake (10.1.0)
Installing i18n (0.6.9)
Using minitest (4.7.5)
Using multi_json (1.8.2)
Using atomic (1.1.14)
Using thread_safe (0.1.3)
Using tzinfo (0.3.38)
Using activesupport (4.0.1)
Using builder (3.1.4)
Using erubis (2.7.0)
Using rack (1.5.2)
Using rack-test (0.6.2)
Using actionpack (4.0.1)
Installing mime-types (1.25.1)
Using polyglot (0.3.3)
Using treetop (1.4.15)
Using mail (2.5.4)
Using actionmailer (4.0.1)
Using activemodel (4.0.1)
Using activerecord-deprecated_finders (1.0.3)
Using arel (4.0.1)
Using activerecord (4.0.1)
Using bundler (1.3.5)
Using coffee-script-source (1.6.3)
Using execjs (2.0.2)
Using coffee-script (2.2.0)
Using thor (0.18.1)
Using railties (4.0.1)
Using coffee-rails (4.0.1)
Using hike (1.2.3)
Installing jbuilder (1.5.3)
Using jquery-rails (3.0.4)
Using json (1.8.1)
Installing mysql2 (0.3.14)
Using tilt (1.4.1)
Installing sprockets (2.10.1)
Using sprockets-rails (2.0.1)
Using rails (4.0.1)
Using rdoc (3.12.2)
Using sass (3.2.12)
Using sass-rails (4.0.1)
Using sdoc (0.3.20)
Installing turbolinks (2.0.0)
Installing uglifier (2.3.2)
Your bundle is complete!
Use bundle show [gemname] to see where a bundled gem is installed.
<<--

 オプションなしでプロジェクトを作成したときとの違いは、作成時の出力で下記のように示されている通り、mysqlのgemが使用されます。

sh>>
Installing mysql2 (0.3.14)
<<--

 また、sqlite3は使用されなくなるので、下記のようなsqlite3に関する出力はなくなります。

sh>>
Using sqlite3 (1.3.8)
<<--

 作成される config/database.yml の差分は下記の通りです。

diff>>
$ diff test_app/config/database.yml turntable_test/config/database.yml
1,2c1
< # SQLite version 3.x
< # gem install sqlite3

MySQL. Versions 4.1 and 5.0 are recommended.

4,5c3,10
< # Ensure the SQLite 3 gem is defined in your Gemfile
< # gem 'sqlite3'


Install the MYSQL driver

gem install mysql2

Ensure the MySQL gem is defined in your Gemfile

gem 'mysql2'

And be sure to use new-style password hashing:

http://dev.mysql.com/doc/refman/5.0/en/old-client.html

7,8c12,14
< adapter: sqlite3
< database: db/development.sqlite3


adapter: mysql2
encoding: utf8
database: turntable_test_development
10c16,18
< timeout: 5000


username: root
password:
socket: /tmp/mysql.sock
16,17c24,26
< adapter: sqlite3
< database: db/test.sqlite3


adapter: mysql2
encoding: utf8
database: turntable_test_test
19c28,30
< timeout: 5000


username: root
password:
socket: /tmp/mysql.sock
22,23c33,35
< adapter: sqlite3
< database: db/production.sqlite3


adapter: mysql2
encoding: utf8
database: turntable_test_production
25c37,39
< timeout: 5000


username: root
password:
socket: /tmp/mysql.sock
<<--

 sqlite3 の設定が mysql 用の設定に変更されているのがわかります。username, password などは適宜変更します。
 binstubsを実行してから、rake でDBを作成します。

sh>>
$ bundle --binstubs
$ bin/rake db:create
<<--

 mysqlにログインしてDBが作成されていることを確認します。

sql>>
mysql> show databases;
+----------------------------+
| Database |
+----------------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
| turntable_test_development |
| turntable_test_test |
+----------------------------+
6 rows in set (0.00 sec)
<<--

 動作確認用のサンプルとしてUserModelを作成します。

sh>>
$ bin/rails generate model User name:string email:string
invoke active_record
create db/migrate/20131211224446_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
<<--

 migrate を実行してDBにテーブルを作成します

sh>>
$ bin/rake db:migrate
== CreateUsers: migrating ====================================================
-- create_table(:users)
-> 0.0110s
== CreateUsers: migrated (0.0111s) ===========================================
<<--

 下記のようにテーブルが作成されていれば成功です。

sh>>
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| email | varchar(255) | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
<<--

posted by akanuma akanuma on Thu 12 Dec 2013 at 08:03 with 0 comments

 私物のMacBook AirにMySQLをインストールしました。せっかくなので手順をメモしておきます。

 インストール自体はHomebrewでコマンド一発です。

sh>>
$ brew install mysql
Warning: It appears you have MacPorts or Fink installed.
Software installed with other package managers causes known problems for
Homebrew. If a formula fails to build, uninstall MacPorts/Fink and try again.
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/mysql-5.6.1
######################################################################## 100.0%
==> Pouring mysql-5.6.15.mavericks.bottle.tar.gz
==> Caveats
A "/etc/my.cnf" from another install may interfere with a Homebrew-built
server starting up correctly.

To connect:
mysql -uroot

To have launchd start mysql at login:
ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
Then to load mysql now:
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
Or, if you don't want/need launchctl, you can just run:
mysql.server start
==> /usr/local/Cellar/mysql/5.6.15/bin/mysql_install_db --verbose --user=akanuma
==> Summary
/usr/local/Cellar/mysql/5.6.15: 9410 files, 349M
<<--

 インストール後の各手順については上記のインストール時の出力に示されています。
 まずOS起動時にMySQLが起動するように設定します。

sh>>
$ ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
/Users/akanuma/Library/LaunchAgents/homebrew.mxcl.mysql.plist -> /usr/local/opt/mysql/homebrew.mxcl.mysql.plist
<<--

 launchctlコマンドで起動します。

sh>>
$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
$ ps aux | grep mysql
akanuma 2558 0.0 0.0 2423468 332 s000 R+ 10:54PM 0:00.00 grep mysql
akanuma 2555 0.0 5.3 3081112 448512 ?? S 10:54PM 0:00.40 /usr/local/Cellar/mysql/5.6.15/bin/mysqld --basedir=/usr/local/Cellar/mysql/5.6.15 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/Cellar/mysql/5.6.15/lib/plugin --bind-address=127.0.0.1 --log-error=/usr/local/var/mysql/Hiroakis-MacBook-Air.local.err --pid-file=/usr/local/var/mysql/Hiroakis-MacBook-Air.local.pid
akanuma 2467 0.0 0.0 2436436 1008 ?? S 10:54PM 0:00.02 /bin/sh /usr/local/opt/mysql/bin/mysqld_safe --bind-address=127.0.0.1
<<--

 mysqlコマンドで接続できることを確認します。

sh>>
$ mysql -uroot
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.15 Homebrew

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
<<--

posted by akanuma akanuma on Tue 10 Dec 2013 at 23:19 with 0 comments

 仕事でRailsを使うことになり、APサーバの選定にあたってPuma, Unicorn, Passenger の比較検討を行いました。方法としてはJMeterでAPサーバにデプロイしたRailsアプリケーションに対して負荷をかけられるだけかけるというやり方です。


# 試験環境

試験の環境としては下記の構成です。

  • Ruby2.0, Rails4
  • アプリケーションサーバ:1台(VM)
  • JMeterサーバ:3台(VM)
  • JMeterクライアント:1台(通常の作業PC)
    |caption=サーバ構成
    |
    |hostaname, CPU, 仮想コア数(Per CPU), Memory, Disk, 用途
    |
    |loadtest01, 2, 4, 8192MB, 20GB, APサーバ
    |loadtest02, 1, 1, 4096MB, 20GB, JMeterサーバ
    |loadtest03, 1, 1, 4096MB, 20GB, JMeterサーバ
    |loadtest04, 1, 1, 4096MB, 20GB, JMeterサーバ

# サーバアーキテクチャの比較

各APサーバのアーキテクチャの比較は下記の通りです。

|caption=各APサーバのアーキテクチャの比較
|
|, Puma, Unicorn, Passenger
|
|デプロイモデル, Reverse Proxy, Reverse Proxy, Nginx Module
|Process/Thread, Multi Processes / Multi Threads, Multi Processes / Single Thread, Multi Processes / Single Thread(OSS Edition)
|||, ||, ||, Multi Processes / Multi Threads(Commercial Edition)
|その他特徴, Workerプロセスごとにスレッドを立ち上げる, Pull型(Workerプロセス側からキューのタスクを取得しにいく), トラフィックに応じてプロセス数を自動調整。商用Editionのみマルチスレッド利用可能


# 処理内容

処理内容としては、純粋にAPサーバの処理能力の比較にするため、DBアクセス等はせず、フィボナッチ数列を計算して返す処理を行います。ロジックは書きサイトを参考にしました。

Rubyでメモ化を使ってフィボナッチ数を求める

ruby>>
class StaticPagesController < ApplicationController

def fibonacci
@fibonacci = calc_fibonacci(params[:n].to_i)
end

private

def calc_fibonacci(n)
  if (n < 2)
    return n;
  else
    p2 = 0;
    p1 = 1;
    2.upto(n) { p2, p1 = p1, p2 + p1 }
    return p1;
  end 
end

end
<<--


# JMeterシナリオ

JMeterのシナリオとしては、

  • JMeterスレッド数:100
  • Ramp up:0
  • ループ数:無限ループ
  • 継続時間:5分間

という内容です。
JMeterのシナリオファイルはこちらから取得できます。


# APサーバごとの設定値による差の検証

まずは各APサーバごとに、設定値の変更による差を検証しました。


## Puma

|caption=Puma検証
|
|ワーカプロセス数, スレッド数, サンプル数, 平均値(msec), 中間値(msec), 90%LINE (msec), 最小値(msec), 最大値(msec), スループット(/sec), KB/sec, エラー数
|
|1, 500, 43079, 2090, 1978, 2379, 129, 2519, 141.68, 414.67, 多発
|100, 8, 241811, 365, 57, 1071, 6, 46414, 799.43, 2339.49, 0
|100, 32, 243620, 362, 60, 1136, 6, 16890, 805.37, 2356.83, 32
|64, 32, 242825, 365, 51, 1355, 7, 103157, 802.35, 2347.94, 1
|32, 32, 241934, 366, 46, 760, 6, 252504, 798.24, 2335.89, 0
|16, 64, 237270, 373, 31, 339, 6, 298546, 782.00, 2288.34, 0
|16, 96, 231996, 382, 37, 644, 6, 241748, 762.49, 2231.26, 0

  • ワーカプロセス数1のケースでは全くCPUを使い切れていませんが、他のケースではCPUを使い切った状態で動いていました。
  • スレッド数を増加させてもリソースの使用量はあまり変化しませんでしたが、プロセス数を増やすと使用量がかなり増えます。
  • メモリに余裕があってもCPUが振り切る方が早いです。

## Unicorn

|caption=Unicorn検証
|
|ワーカプロセス数, サンプル数, 平均値(msec), 中間値(msec), 90%LINE (msec), 最小値(msec), 最大値(msec), スループット(/sec), KB/sec, エラー数
|
|1, 4294, 11345, 572, 50553, 77, 176247, 11.74, 34.54, 433
|8, 8686, 6026, 562, 13721, 77, 141193, 22.15, 65.15, 389
|32, 42943, 1465, 325, 2844, 51, 183552, 103.48, 304.38, 280
|64, 191254, 440, 170, 375, 26, 115819, 498.54, 1466.46, 48
|96, 247191, 360, 170, 261, 49, 82454, 773.58, 2275.69, 3
|128, 256050, 343, 252, 452, 13, 20587, 836.00, 2459.82, 0
|160, 254117, 347, 291, 537, 15, 8825, 835.54, 2458.54, 0
|192, 252158, 349, 302, 588, 13, 5746, 833.94, 2453.87, 0
|224, 229723, 383, 275, 592, 9, 299799, 697.12, 2045.15, 2

  • ワーカプロセス数が1の場合は1CPUしか使われない
  • ワーカプロセス数をコア数と同じ8にした場合でも、すべてのコアが使われるわけではない
  • ワーカプロセス数をコア数の4倍の64まで増やすとかなりCPUが使われるようになってきて、128まで増やすとCPUはほぼ使い切られて、メモリの使用率も高くなる。
  • ワーカプロセス数を192まで増やした時点でメモリもほぼ使い切られ、224まで増やすとメモリが足りなくなり、Swapが発生して遅くなる。

## Passenger

|caption=Passenger検証
|
|プロセス数, サンプル数, 平均値(msec), 中間値(msec), 90%LINE (msec), 最小値(msec), 最大値(msec), スループット(/sec), KB/sec, エラー数
|
|1, 65188, 1376, 1282, 1325, 1224, 8690, 215.15, 646.07, 0
|8, 245153, 360, 355, 368, 297, 2441, 810.57, 2433.99, 0
|16, 246737, 357, 353, 381, 279, 2339, 815.77, 2448.77, 0
|24, 241165, 366, 360, 391, 281, 2414, 797.27, 2392.30, 0

  • プロセス数が1だと4コアしか使われていない
  • プロセス数をコア数と同じにするとどのコアもかなり使われるようになる。メモリは余裕あり。
  • プロセス数をコア数以上に増やしていってもCPU, メモリの使用率はあまり変化しない。CPUは80%まで使われることが多いが、アイドルが10%前後残っていて、使い切ることはない

# 各APサーバの最適値同士を比較

各APサーバの最適値同士を比較して、使用するAPサーバを決定する

|caption=総合
|
|APサーバ, サンプル数, 平均値(msec), 中間値(msec), 90%LINE (msec), 最小値(msec), 最大値(msec), スループット(/sec), KB/sec
|
|Puma, 241811, 365, 57, 1071, 6, 46414, 799.43, 2339.49
|Unicorn, 252158, 349, 302, 588, 13, 5746, 833.94, 2453.87
|Passenger, 246737, 357, 353, 381, 279, 2339, 815.77, 2448.77

  • Pumaはスループットが一番低いのに加えて最大値、90%LINEの遅さ、不安定さで候補から除外。
  • Passengerは安定しているが最小値が他の2つに比べて大きい。90%LINE、最大値は優秀。
  • Unicornはスループットが一番大きいのと、最小値、平均値も悪くない。最大値、90%LINEがPassengerと比 べると遅いのが懸念点。

|caption=定数スループットタイマを使って実際のアクセス数に近い負荷でUnicornとPassengerを比較
|
|APサーバ, サンプル数, 平均値(msec), 中間値(msec), 90%LINE (msec), 最小値(msec), 最大値(msec), スループット(/sec), KB/sec
|
|Unicorn, 23075, 12, 10, 13, 4, 116, 75.32, 221.50
|Passenger, 23092, 11, 9, 12, 5, 118, 75.38, 226.67

  • UnicornとPassengerでほぼ差はなし
  • Passengerは最初の比較時に他と比べて最小値が遅いことが懸念だったが、実際の状況に近いアクセス数では 問題なく、Unicornが負荷が低い状態でもメモリリソースを消費するのに対してPassengerはリソースの消費が少ないこと から、Passengerを第一候補と考える。

# 検証時の問題点

検証時に発生した問題点を参考までに記載しておきます。


## Passenger
  • デフォルトの状態で負荷をかけたところ、下記のようなエラーが多発してHTTPステータスコード 503が返される。

sh>>
[ 2013-11-20 12:21:13.0578 17419/7fbbbc9da700 Pool2/Group.h:331 ]: Request queue is full. Returning an error
<<--

リクエストのQueueがあふれたことによるもののようです。Queue のサイズのデフォルトは100なので、無制限にするために passenger_max_request_queue_size を0に設定したところ、エラーは出なくなりました。


## Unicorn
  • Nginxとの連携をUnixドメインソケットで行う設定で負荷をかけたところ、下記エラーが多発。

sh>>
2013/11/20 11:32:35 [error] 27462#0: *622742 connect() to unix:///home/test_user/server-proto/unicorn.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 192.168.51.234, server: loadtest01.test.com, request: "GET /fibonacci?n=1000 HTTP/1.1", upstream: "http://unix:///home/test_user/server-proto/unicorn.sock:/fibonacci?n=1000", host: "loadtest01.test.com:3090"
<<--

下記サイトなどを参考に、TCPポートによる連携に変更しました。

[http://www.faultserver.com/q/answers-need-to-increase-nginx-throughput-to-an-upstream-unix-soc ket-linux-kernel-tun-398972.html](http://www.faultserver.com/q/answers-need-to-increase-nginx-throughput-to-an-upstream-unix-soc ket-linux-kernel-tun-398972.html)

変更後に負荷をかけたところ、エラーは概ね解消しました。負荷をかけ続けていると、件数は少なくなったもののエラーが発生しました。HTTPステータスコードは 502 Bad Gateway

sh>>
2013/11/20 14:45:29 [error] 25979#0: *254606 upstream prematurely closed connection while reading response header from upstream, client: 192.168.51.232, server: loadtest01.nubee.com, request: "GET /fibonacci?n=1000 HTTP/1.1", upstream: "http://127.0.0.1:3070/fibonacci?n=1000", host: "loadtest01.test.com:3090"
<<--

sh>>
[2013-11-20 14:44:09.109250] ERROR worker=114 PID:26737 timeout (31s > 30s),
killing
[2013-11-20 14:44:09.119595] ERROR reaped #<Process::Status: pid 26737 SIGKILL
(signal 9)> worker=114
[2013-11-20 14:44:10.140398] INFO worker=114 ready
<<--

検証のためにUnicorn側のタイムアウト設定を大幅に増やしました。30秒 → 300秒に変更。Nginxの設定にも下記を追加しました。

sh>>
send_timeout 300;
proxy_connect_timeout 300;
proxy_read_timeout 300;
<<--

これでひとまずエラーは回避できました。。スループットの検証のためにタイムアウト値を大きくしていますが、実際の環境ではタイムアウト値は小さく設定する必要があります。

posted by akanuma akanuma on Sun 8 Dec 2013 at 00:06 with 0 comments

MongoDB Advent Calendar 2013 の 5日目です。

 先日、MongoDB University M101P コースのTAをさせていただく機会に恵まれました。MongoDB University というのはMongoDB社が提供している、MongoDBを使用したプログラミングについてオンラインで学習できるコースです。

スクリーンショット 2013-12-01 18.00.25.png

 TA(Teaching Assistant) というのはコース内のフォーラムで、受講している生徒からの質問等に回答するのが主な役割です。以前は英語版のコースのみだったのですが、Pythonを使用したプログラミングの学習コース(M101P)のビデオが日本語でも提供されることになり、日本語を話す受講者のために日本人のTAが必要ということになりました。MongoDB University の各コースでは修了時にアンケートをとっていて、以前私が英語版で受講したときのアンケートで、TAや翻訳等の機会があれば協力しても良いか、という質問にYesと回答していたためにオファーをいただいたようです。TAを努めたそのコースも先日終了したので、感じたことや気づいたこと等書いてみたいと思います。MongoDBの技術的な話とはちょっと違ってしまいますが、ご容赦ください。

  1. 日本語での生徒からの投稿ゼロ

     まず結果として日本語でのフォーラムへの投稿数はというと、残念ながら0でした。日々フォーラムをチェックしていると、英語でのポストはどんどん増え、活発にやりとりされていくのですが、日本語でのポストはないまま終わってしまいました。そもそもJapanese Speakerの受講者がEnglish Speakerに比べてかなり少ないということはあると思いますが、こういったところでの積極性はやはり日本人よりも欧米の方々の方が強いのかなぁと思いました。

  2. 使用しているバージョンや環境などによる違いが大きい

     M101PはPythonを使用したプログラミングについてのコースで、前提としているPythonのバージョンは2.7であることも記載されているのですが、3系を使用しているために提供されているコードが正しく動作しないというポストがかなり多く見られました。また、シンプルにローカルのPC上で動かす意外にも、OpenShift などのクラウド環境で動かそうとしているがうまくいかない、というような内容もありました。私自身はローカルのPC上で動かす意外には業務でAWS上のMongoDBのクラスタ環境に触れる機会はあるのですが、それ以外に多くの環境で動作させた経験はなく、さらにOSもLinux, MacOS, Windowsなどによって細かい点はだいぶかわってくるので、様々な環境の理解や、MongoDBがどのように動作するかの詳細の理解が全く足りていないなぁと感じました。コースの範囲としてどこまでカバーするかというのはありますが、TAとして関わる以上はできるだけ助けになるような回答をしたいと思っています。

  3. MongoDBの詳細な仕様について理解することが重要

     質問では、コースのビデオの中では解説していない細かい点についても質問がくることがあります。例えばexplainの出力のこの項目はこっちの項目とどう違うんだ、とか、こういう用途でMongoDBを使う場合は、モデリングはどっちが向いているのか、など。自分がユーザとして使う分には知らなくても特に困らないような問題でも、やはりTAとして回答するには色々理解している必要があります。また、前項の内容に関連して、詳細を理解していないと他の環境で使ったときの動作がわからないということも出てきます。

  4. 英語力重要

     TAとしては一応日本語担当なのですが、日本語でのポストもありませんでしたし、TAである以上は英語のポストにも回答していきたいと思うのですが、まだまだ自分の英語力は不足していて、質問の意図を理解しきれなかったり、理解するまでに時間がかかってしまうことが多く、他のTAの方にお任せするということになって悔しい思いをしました。もちろん英語力だけでなく前述の技術的なところの不足に起因する部分も多いのですが、やはり英語ができないことでのデメリットを痛感しました。TAのオファーをいただいたときにも、最初にMongoDBの方とSkypeでミーティングをしたのですが、もちろん英語でのミーティングで、私の受け答えもかなり怪しかったので、MongoDBの方を不安にさせたのではないかと思っています。。

     受講する側で考えたときも、今回のコースについてはビデオは日本語でのボイスオーバーが提供されているものの、各週のホームワークや最終試験はすべて英語ですので、技術的には理解していても設問が理解できないと回答できません。フォーラムでのやりとりも参考になるものも多いので、やはり英語ができることでのメリットは大きいです。

  5. アウトプット重要

     TAのオファーをいただいたとき、受けるかどうかかなり迷いました。MongoDBの知識に自信があったわけでもありませんでしたし、ユーザグループで積極的に活動していたわけでもなかったので、務まるだろうかとかなり不安でした。でも逆にこれによってMongoDBのことをさらに知る機会にもなるかもしれないし、英語力をアップさせるためにも英語を使う機会を増やしたいと思っていたので、思い切って受けることにしました。結果としてはやって良かったと思っています。コース期間中は日々フォーラムをチェックする必要がありましたし、受講者の方は回答を待っているので気が休まりませんでしたが、おかげでアウトプットの機会も増え、また、このAdvent Calendarにも参加するためのネタにもなりました。もちろん自分で黙々とスキルアップに励む時間も大切なのですが、アウトプットすることによって得られることも多いので、今後も機会があれば積極的にアウトプットする場を作っていきたいと思っています。

 M101Pコースは11/25からまたスタートしています。MongoDBについて一通り学習するにはとても良いコンテンツだと思いますので、興味のある方は是非受講してみてください。前回のコースで日本語での質問がなかったので今回のコースでは日本語対応のTAはアサインされていませんが、ビデオは日本語対応されていますので、英語が不安な方も大丈夫だと思います。

 以上、MongoDB Advent Calendar 2013 5日目でした。

posted by akanuma akanuma on Thu 5 Dec 2013 at 08:39 with 0 comments

dispatch_async , dispatch_group_async で sleep する JOB はいくつでも走らせられるが、dispatch_apply では実スレッド数分しか走らない。

dispatch_async , dispatch_group_async では JOB が sleep すると実スレッドを他の JOB が再利用するようだが、dispatch_apply はしない?

ruby>>
#include <stdio.h>
#include <dispatch/dispatch.h>

static long long
Sum( long long p = 1000000000 )
{ long long v = 0;
for ( long long i = 1; i <= p; i++ ) v += i;
return v;
}

void
Apply()
{
__block long long sum = 0;

dispatch_apply
(   10  
,   dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ) 
,   ^( size_t p ) 
    {   printf( ">>%zd\n", p );
        sum += Sum();
        printf( "<<%zd\n", p );
    }   
);  

printf( "sum = %lld\n", sum );

}

void
GroupAsync()
{
__block long long sum = 0;

dispatch_group_t wG = dispatch_group_create();
dispatch_queue_t wQ = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 );
for ( int i = 0; i < 10; i++ )
{   dispatch_group_async
    (   wG  
    ,   wQ  
    ,   ^() 
        {   printf( ">>%zd\n", i );
            sum += Sum();
            printf( "<<%zd\n", i );
        }   
    );  
}   
dispatch_group_wait( wG, DISPATCH_TIME_FOREVER );
dispatch_release( wG );
printf( "sum = %lld\n", sum );

}

void
Async()
{
__block long long sum = 0;

dispatch_queue_t wQ = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 );
for ( int i = 0; i < 10; i++ )
{   dispatch_async
    (   wQ  
    ,   ^() 
        {   printf( ">>%zd\n", i );
        //  sum += Sum();
            sleep( 7 );
            printf( "<<%zd\n", i );
        }   
    );  
}   
dispatch_main();

}

<<--

posted by Saturn Saturn on Fri 29 Nov 2013 at 00:25 with 0 comments

今まで自作ツールを使っていましたが、そろそろchefを使ってみようかといろいろ試しています。
knife.rbの探索順序の問題でハマったのでメモ。

knife-ec2を使ってインスタンス一覧を見ようと思ったのですが、

pre>>
% knife ec2 server list
ERROR: You did not provide a valid 'AWS Access Key Id' value.
ERROR: You did not provide a valid 'AWS Secret Access Key' value.
<<--

あれれ? 確かに ~/.chef/knife.rb に設定してあるはずなのだけれど...
悩むこと数十分。

knifeコマンドはデフォルトで ~/.chef/knife.rb を探しに行くと思っていたのですが、カレントディレクトリ直下に .chef/knife.rb というファイルがある場合はそちらを優先するようです。

posted by genki genki on Sun 24 Nov 2013 at 19:39 with 0 comments

何らかの原因でgemのファイルが壊れたことが想定される場合、
以下のようにすると全てのインストール済みgemを初期状態に戻すことができます。

pre>>
gem pristine --all
<<--

posted by genki genki on Fri 22 Nov 2013 at 14:56 with 0 comments

たぶん、mach_absolute_time で取った値が渡されているようなので、
mach_timebase_info による調整をしてやる必要がある。

ruby>>
mach_timebase_info_data_t TB;
mach_timebase_info( &TB );

<<--
としておいてコールバックの中で

ruby>>
pTimeStamp->mHostTime * TB.numer / TB.denom;

<<--

とすると nano second になる。

posted by Saturn Saturn on Mon 18 Nov 2013 at 11:00 with 0 comments

一行ですが

pre>>
curl -L http://toolbelt.treasure-data.com/sh/install-ubuntu-lucid.sh | sh
<<--

簡単になったなー

posted by genki genki on Sun 17 Nov 2013 at 23:32 with 0 comments
Contents rssrss
Leading Smart TV App Development Companies | USA | 4 Way Technologies
Apple TV Developer | TVOS Development | USA | 4 Way Technologies
光ファイバーを二次元振動させて走査するAR用ディスプレイ
因果の取り違え
Value Transformer
Swift2's defer for CoffeeScript
mongodb-3.0からcreateIndexのdropDupsが無くなったらしい
mongodb-3.0以降のWiredTigerの設定を動的に変更する方法
一般楕円の高速生成アルゴリズムへの道標
farro mantecatoのレシピ
Tags
railsPassengerAppdevelopmentDevelopment,MongoDBmysqlRails,Ruby,TVapplebootstrapChefcoffeescriptCompanies,CouchbasedatetimepickerdeferDeveloper,groonga
Comments rssrss
https://stosastudio.ru/catalog/kuhni-lounge/ https://stosastudio.ru/catalog/kuhni-lounge/: Фабрика Tessarolo https://stosastudio.ru/vybiraem-... 04/06 08:14
瀧内元気 瀧内元気: MacOS版は以下にあります * [genki/ViMouse](https://github.c... 01/16 05:40
KingofSmack KingofSmack: Here also good reads for this mobile application d... 05/10 18:02
Spencer Spencer: You don't have to re-compile it, this version work... 04/08 07:15
staiano staiano: Any chance we can get a recompile for 10.9? 01/10 01:47
dsjf dsjf: https://gist.github.com/6bf1bf2c3cbb5eb6e7a7 これでも出... 01/08 23:23
yoku0825 yoku0825: nkfの方が使いやすいですが、glibcに含まれているiconvの方が 確実にどの環境にも入っている... 06/11 07:03
falsefalse falsefalse: @tiancongxin try using this one https://github.com... 02/14 08:04
Services from s21g
twpro(ツイプロ)
Twitterプロフィールを快適検索
地価2009
土地の値段を調べてみよう
MyRestaurant
自分だけのレストラン手帳
Formula
ブログに数式を埋め込める数式コミュニティ