►
Description
Bogdan Kolbik
Optimization Algorithm Developer at MOIA
We managed to rewrite the core of a big Scala application in Rust while keeping all the supporting code untouched. This talk is about how we did it, what problems we faced and how we solved them. It involves JNI, Protobuf, Trojan horses, and a reference to The Hitchhiker’s Guide to the Galaxy.
A
Hello
I'm,
going
to
tell
you
how
we
use
rust
inside
the
gvm
application
and
at
this
moment,
you're
probably
full
of
questions
like
how
why
why
you
I
will
answer
them
in
a
reverse
order:
I'm
Bogdan
I'm,
a
software
engineer
enough
about
me.
I
work
at
the
lead,
optimization
team
at
Moya,
and
we
drive
this
beautiful
golden
buses
and
we
provide
the
right
pooling
service,
new
questions.
What
is
the
right
pulling
and
how
is
it
different
from
the
pool
riding?
A
Imagine
you
want
home?
It
happens
sometimes,
and
there
is
a
vehicle
that
can
take
you
from
the
stop
near
where
you
are
to
the
stop
near
your
home
and
deliver
you
and
it
can
deliver
other
passengers
in
the
meantime,
that's
right
pulling.
We
have
once
we
make
routes
for
them
dynamically,
depending
on
the
requests
from
the
people,
and
that's
also
what
our
team
does
the
optimization
problem.
We
have
the
whole
city
of
vehicles,
we
have
the
whole
city
of
trips
and
we
try
to
assign
trips
to
vehicles
to
make
everyone
happier.
A
Optimization
problems
are
hard
and
be
hard.
It
means
that
there
are
many
feasible
Solutions,
but
some
of
them
are
better
than
other
ones,
and
if
you
get
one
solution,
you
cannot
know
if
it's
the
best
one
or
not
to
make
sure
it's
the
best
one.
Usually
you
have
to
compare
it
to
every
other
possible
solution
and
it
might
take
years,
and
we
need
to
solve
this
problem
every
few
seconds.
A
You
need
to
do
it
in
you,
but
usually
optimization
problems
are
quite
common
and
they
have
common
Solutions
and
one
thing
is
try
as
many
solutions
as
possible
within
a
time
limit
and
return
the
best
one
you
could
find
in
this
time
and
this
kind
of
solving
the
problem
so
General.
So
we
have
General
solvers
for
optimization
problem
and
some
of
them
are
even
open
source.
So
we
used
one
of
them.
A
It's
a
Java
Library
called
opta
planner,
open
source
solver
and
when
we
need
to
set
up
everything
quickly,
we
just
build
a
scholar
service
around
this
library
and
if
you
know
don't
know
what
is
color,
it's
a
functional
programming
language
that
runs
in
JM,
so
it
can
use
the
features
of
java.
It
can
use
the
libraries
of
java,
and
during
this
talk
in
your
head,
you
can
just
replace
every
occurrence
of
this
color
board
with
Java
and
it
will
be
okay.
A
I
thought
it's
completely
wrong,
but
let's
get
back
to
our
Auto
planner
we're
on
it.
It
gives
us
some
answer
and
we
can
either
accept
it
or
we
can
actually
that's
everything
we
can
do
if
we
don't
know
why
exactly
this
answer,
we
don't
know
what
other
answers
we
considered
and
why
this
one
was
picked.
A
If
you
want
to
fit
as
many
operations
as
possible
within
a
fixed
time
limit,
it
has
memory
safety
and
nice
high
level
features,
meaning
the
development
is
fast.
When
you
want
to
implement
an
algorithm.
The
language
won't
stand
in
your
way,
and
you
can
you
have
a
permission
to
use
a
rocket
emoji
for
your
whole
lifetime,
which
is
also
important
and,
in
general,
Moya,
loves
rust,
with
a
love
ruined
by
laptop
stickers.
A
It's
not
the
first
implementation
in
Rust
and
now
company,
not
the
last
one
and
everyone's
happy
so
far.
But
if
writing
takes
time.
You're
writing
big
things
takes
a
lot
of
time
and
every
time
you
just
finished,
rewriting
something
and
you're
switching
there's
a
small
chance,
sometimes
not
small,
to
crush
your
whole
service
in
production.
At
the
moment
of
this
switch
and
the
bigger
change
you've
made
the
bigger
the
chances
to
break
everything,
put
everything
on
fire
and
our
service
is
quite
big.
There's
a
lot
of
small
text
over
here.
A
A
That's
why
we
need
to
consume
a
balance,
send
them
to
dynamodb.
Every
time
we
get
a
request.
We
need
to
load
additional
data
from
dynamodb
aggregate
everything
there's
a
decision
tree
involved.
Then
we
map
everything
to
real,
optimization
problem,
run
optimization,
and
then
we
have
the
same
problem
because
our
clients
don't
think
in
terms
of
optimization
solution.
So
you
have
to
map
everything
back
and
there's
a
lot
of
stuff
going
on
so
you're
writing.
Optimizer
is
very
good.
It
provides
us
a
lot
of
business
value.
We're
writing
everything
else.
A
It's
already
good.
So
by
wasting
time
rewriting
it
we
just
waste
time
and
we
just
increase
the
chance
of
making
everything
burn
so
into
words.
Green
Parts,
good
to
riverwrite,
Red,
part
better
right
and
it's
all
a
single
application
and
I
use
computer
Graphics
to
make
red
part
look
much
bigger
than
green
one.
A
Now,
how
about
we
write
on
the
green
part
and
say:
okay,
we're
done
it
would
mean
that
we
use
two
languages
in
the
same
application.
Is
it
possible
yes,
yeah?
For
you,
the
title
of
the
talk
is
already
a
spoiler
for
us.
It
was
a
mystery
for
about
five
minutes
of
Googling.
Then
it
turned
out
yes,
it's
possible
because
of
Jay
and
I.
A
It's
a
Java
native
interface
thing
that
lets
Java
applications,
call
native
libraries
and
vice
versa,
think
that
let's
C,
plus
plus
or
C
applications
called
Java
libraries
looks
like
it
was
done
long
time
ago
to
simplify
migration
from
the
C
plus
plus
code
bases
to
Java,
but
it's
still
supported
and
it's
still
used
mostly
by
Android
developers,
looks
like
they
don't
want
to
write
Java
and
they
want
to
write
rust
instead,
I
cannot
blame
them
for
this,
so
we
can
use
jni.
So
how
to
do
this?
A
Let's
keep
my
something
like
this.
You
have
a
lot
of
java
codes
and
when
you
pass
it
through
Java
compiler,
you
can
get
the
Java
binary
and
also
header
files
for
Co,
C,
plus
plus
programs.
Then
you
write
implementation
for
these
header
files
in
C,
plus,
plus
you
compile
it
and
yeah
you
get
a
binary
native
Library,
that's
that
can
work
together
with
Java
and
they
support
it.
A
A
There
are
some
nice
crates
for
supporting
Jay
and
I.
Invest.
We
use
Robusta
gni
because
it
doesn't
depend
on
this
header
file.
So
instead
you
have
two
files,
hope
you
can
read
it,
but
if
you're
not
you're
not
losing
much
below,
you
have
the
Scala
part,
which
is
a
class
with
a
single
function
string
to
string
function
there
without
any
implementation.
Instead,
it
has,
it
has
a
native
a
attribute
which
means
implementation
is
somewhere.
A
Trust
me
I'm,
an
engineer
and
above
you
have
the
same
struct
with
the
same
name
with
the
same
function
and
some
boilerplate
and
macro
calls
copy
pasted
from
example,
of
robusto
gni,
and
that's
all
you
have
to
do.
It
works
together.
Nice.
It
supports
much
more
complex
things
like.
As
than
a
single
function
that
is
string
to
string.
You
can
have
multiple
functions.
You
can
save
some
State
between
the
calls
and
reuse
it
when
your
library
is
called
Next,
but
you
don't
have
to
use
it.
The
one
difference
is
on
scholar.
A
You
have
a
string
to
string
function
and
in
Rust
you
have
link
to
result
of
string
and
it
will
be
important
later,
but
in
general
it's
a
proof
of
concept.
It
works
nice.
Now
we
can
think
how
to
implement
it
in
the
real
application,
which
means
how
to
connect
Optimizer
and
coordinator
coordinator
is
all
the
application
except
optimizer,
and
when
you
think
about
how
to
do
this,
where
to
place
code,
there
are
some
contradicting
wishes
you
can
have.
A
For
example,
you
want
to
store
Optimizer
and
coordinator
and
different
repositories,
because
these
are
different
applications
written
in
different
languages,
but
at
the
same
time
you
want
rust
and
Scala
interface
for
the
optimizer
to
be
in
the
same
repository,
because
otherwise
it
would
be
very
hard
to
keep
them
in
sync.
Also,
if
you
want
to
run
coordinator
locally
or
in
Ci
or
on
production,
you
want
to
use
Optimizer
inside
it
and
you
need
to
have
a
different
builds
because
trust
is
not
working
on
the
virtual
machine.
A
A
We
have
a
very
small
scalar
library
that
provides
the
same
interface
as
the
rust
Optimizer
and
it's
in
the
same
repository
with
the
rest
Optimizer,
but
it
doesn't
do
anything
it
just
forwards.
The
request
to
the
rust
implementation,
but
then
everything
is
packed
as
a
single
Scala
Library
deployed
as
a
scholar,
library
and
coordinator
depends
on
it
as
on
a
Scala
Library.
So
it
doesn't
even
note
that
there
is
a
rust
inside,
which
is
quite
good
for
the
clients
which
have
us
in
this
case,
but
still
good
build
process
in
this
case
is
also
interesting.
A
You
have
rust
code,
we
compile
it
in
both
operational
systems.
We
care
about
or
Linux
and
mac,
and
then
we
take
these
binaries
and
add
them
to
resources
of
the
Scala
Library
when
we
build
it.
So
it's
kind
of
static
assets,
so
everything
gets
packed
in
the
one
big
jar
file
we
sent
to
the
dependency
repository
then,
and
it
works
nice
color
Library
will
get
request.
It
loads,
the
rust
library.
That
is
much
in
the
current
operational
system
and
forwards.
A
The
request
there
now
some
technical
details,
pricing
data-
you
have
a
string
to
string
function
in
reality.
Of
course,
our
optimization
problems
and
optimization
Solutions
are
much
more
complex
than
usual
strings
and
Janae
has
some
mapping
stuff.
So
you
can
map
types
from
java
to
rust.
You
can
even
map
arrays
and
objects
and
nested
structures.
Probably
we
didn't
bother
doing
it
because
it
looks
complex
and
it
looks
like
a
tedious
work.
That
is
very
technology
specific.
A
So
if
we
want
tomorrow
to
make
Optimizer
as
a
separate
application
running
and
sewing
Network
requests,
you'll
have
to
throw
away
this
part
of
code
and
we
write
everything
in
somehow
another
way.
So
instead
we
used
broad
above
a
defined
protobuf
messages.
In
the
same
repository
and
during
the
build
we
generate
the
rust
code
and
we
generate
this
color
code,
both
in
the
same
Repository
and
now.
A
If,
when
our
Scala
Library
wants
to
call
the
rust
Library
it
encodes,
everything
in
protobuf
turns
it
into
a
string,
passes
the
string
and
then
arrests
decodes
it,
and
this
is
perfectly
in
sync,
because
everything
is
in
the
same
repository
and
it
works
pretty
good
next
thing
is
error
handling,
and
here
we
have
one
problem
and
rust
phonics.
We
cannot
do
anything
about
it.
On
the
Java
side,
it
just
crashes,
the
whole
application,
and
it's
quite
bad
when
you
have
long
running
applications
that
are
supposed
to
leave.
A
A
Now
we
need
to
have
a
fallback
for
every
case
where
something
might
go
wrong
and
it
turned
out
to
be
a
surprisingly
simple,
because
our
rust
application
doesn't
have
any
external
calls.
So
there
might
cannot
be
any
network
issues,
it
gets
already
type
data
and
we
can
enforce
some
type
checks
on
this
color
side.
A
A
A
So
we
could
do
this
Shadow
run.
We
could
check
for
the
box,
there
was
20
of
them,
we
could
fix
them
and
only
do
a
real
switch
only
when
we're
confident
enough
with
results
that
we
are
doing
so
we
can
do
the
switch
without
crashing
everything,
and
while
we
were
experimenting
with
this
because
it
was
in
the
single
application,
no
one
noticed
we're
doing
this.
A
As
a
result,
it's
brewing
in
production,
it
works
for
more
than
a
year
and
we
never
had
problems
with
this
thing.
After
the
first
implementation
we
get
the
best
from
both
languages,
so
rust
goes
fast
and
Scala
does
networking
and
Amazon
issues
turns
out.
We
managed
to
avoid
all
the
scariest
parts
to
parts
of
rust
and
negative
Parts
is
we
have
to
know
and
be
eager
to
use
both
languages
which
makes
hiring
a
bit
harder,
but,
okay
and
in
general,
the
whole
model.