Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RMagick, migrate to ImageMagick 7 #RubyKaigi #R...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Watson
April 18, 2019
Programming
10k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RMagick, migrate to ImageMagick 7 #RubyKaigi #RubyKaigi2019
Watson
April 18, 2019
More Decks by Watson
See All by Watson
クラウドネイティブ時代に 進化し続けるFluentd
watson
0
24
Magick
watson
0
12k
Improve JSON Performance
watson
2
1k
fastlane 奮闘記
watson
0
95
How to optimize Ruby internal.
watson
3
3.1k
iOS、AndroidアプリをRubyで
watson
1
510
RubyMotion 2.0
watson
6
2.8k
Differences CRuby/MacRuby/RubyMotion
watson
5
5.8k
Other Decks in Programming
See All in Programming
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
1.9k
Oxcを導入して開発体験が向上した話
yug1224
4
300
New "Type" system on PicoRuby
pocke
1
780
RTSPクライアントを自作してみた話
simotin13
0
520
「エンジニアインターン、どうやって取った?」準備のリアルを語るLT会 Progate BAR
akiomatic
0
130
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
200
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
19
6.4k
Agentic UI
manfredsteyer
PRO
0
120
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
150
Spec Driven Development | AI Summit Lisbon
danielsogl
PRO
0
170
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
120
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
160
Featured
See All Featured
Accessibility Awareness
sabderemane
1
130
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
140
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.5k
Building AI with AI
inesmontani
PRO
1
1.1k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
320
Believing is Seeing
oripsolob
1
140
Navigating Weather and Climate Data
rabernat
0
220
Side Projects
sachag
455
43k
Heart Work Chapter 1 - Part 1
lfama
PRO
7
36k
ラッコキーワード サービス紹介資料
rakko
1
3.6M
Documentation Writing (for coders)
carmenintech
77
5.4k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.3k
Transcript
RMagick, migrate to ImageMagick 7 Shizuo Fujita
self.inspect • @watson1978 • Ubiregi, Inc • Ruby committer •
RMagick maintainer
What's RMagick
"RMagick is an interface between the Ruby programming language and
the ImageMagick image processing library."
Active members ˏmockdeep ˏwatson1978 ˏdlemstra
My Motivation
I want to use Ruby ... •Web programming
I want to use Ruby ... •Web programming •iOS programming
I want to use Ruby ... •Web programming •iOS programming
•Image processing
I want to use Ruby ... •Web programming •iOS programming
•Image processing •Machine learning, etc
I want to use Ruby ... •Web programming •iOS programming
•Image processing •Machine learning, etc To meet crazy great people at Ruby World
Current Status of RMagick
None
Fixed major problems since v2.16.0 •Set up •Memory leaks •SEGVs
Set up problems
Set up problems •macOS (Homebrew) •Windows
macOS (Homebrew)
macOS (Homebrew)
Windows •Ruby has some environments • MingW • MSWin •
Cygwin • Windows Subsystem for Linux
Windows •Ruby has some environments • MingW • MSWin •
Cygwin • Windows Subsystem for Linux
MingW...?
Set up : MingW
Solution https://github.com/oneclick/rubyinstaller2/wiki/For-gem-developers
MingW works
MSWin...?
Set up : MSWin
MSWin supported...? Looks like MSWin supporting code...
Not supported... Why !? For MSWin
MSWin works well
Memory leak
Fixed many memory leaks 55 Closed
Case 1 VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) {
Image *image, *new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); }
VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,
*new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory
VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,
*new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory Destroy memory
VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,
*new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory Destroy memory Raise exception with unexpected value
VALUE Image_shear(VALUE self, VALUE x_shear, VALUE y_shear) { Image *image,
*new_image; ExceptionInfo *exception; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); new_image = ShearImage(image, NUM2DBL(x_shear), NUM2DBL(y_shear), exception); rm_check_exception(exception, new_image, DestroyOnError); (void) DestroyExceptionInfo(exception); rm_ensure_result(new_image); return rm_image_new(new_image); } Case 1 Allocate memory Destroy memory Raise exception with unexpected value Unreachable by exception
Case 1: Exception causes Memory Leak image = Magick::Image.read('sample.png').first begin
image.shear('x', 'y') rescue end
Case 2 static VALUE has_attribute(VALUE self, MagickBooleanType....[snip]) { Image *image;
ExceptionInfo *exception; MagickBooleanType r; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); CHECK_EXCEPTION() return r ? Qtrue : Qfalse; }
static VALUE has_attribute(VALUE self, MagickBooleanType....[snip]) { Image *image; ExceptionInfo *exception;
MagickBooleanType r; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); CHECK_EXCEPTION() return r ? Qtrue : Qfalse; } Case 2 Allocate memory
static VALUE has_attribute(VALUE self, MagickBooleanType....[snip]) { Image *image; ExceptionInfo *exception;
MagickBooleanType r; image = rm_check_destroyed(self); exception = AcquireExceptionInfo(); r = (attr_test)(image, exception); CHECK_EXCEPTION() return r ? Qtrue : Qfalse; } Case 2 Allocate memory Missing destroy
Case 2: Missing destroy lead to Memory Leak image =
Magick::Image.read('sample.png').first image.gray?
Case 3 Unnecessary clone API returns NEW image in allocated
memory
Case 3: Memory Leak by incorrect API usage image =
Magick::Image.read('sample.png').first image.sharpen_channel
Case 4
Case 4 Found memory leak in ImageMagick
Case 4
Case 4: Huge software has Memory Leak
How to detect memory leak
Profiler tool
Profiler tool Memory leak detected
Profiler tool
Profiler tool... •Detects at executed code only •unit-test •RSpec •Needs
better coverage...
Code reading... •To find same pattern that profiler detects
SEGV
Closed 5 SEGVs 4 Fixed 1 Workaround
Workaround Case Help wanted
Workaround Case •Call back image processing progress to Ruby User's
Ruby code RMagick ImageMagick Callback
ruby_stack_length() shows 51119378542 = 47 GB • Invalid stack length
• GC running →SEGV
RMagick is better than ever.
Future...
ImageMagick 7 support
Preparing draft code... now
Plan 1: Split RMagick ver 4.x RMagick ver 3.x ver
3.0 ver 3.1 ver 2.16.1 ImageMagick 7 ImageMagick 6
Plan 2 : Mix both ImageMagick 7 ImageMagick 7 ImageMagick
6 Using many #if defined ...
Plan 3: Bundle both ImageMagick 7 ImageMagick 6
We welcome good ideas for the future
Announcement •RubyData Workshop (Tomorrow, 14:20 ~) •RubyKaigi 2019 Code Party
(Tomorrow, 19:00 ~)
Thank you