taking a Go at plugin architecture

2,638 views
Skip to first unread message

RogerV

unread,
Jul 31, 2010, 12:42:26 PM7/31/10
to golang-nuts
Recent discussions on runtime extensibility of Go programs, dynamic
linking - pro/con, etc., are no doubt still fresh in the mind.

I've been wondering about this after following one of those
discussions - could a viable "plugin" architecture for Go be built on
the basis of its static linking approach?

Lets say the goal is to build an editor similar to Eclipse where third
parties can create extension modules.

An extension point API for these external modules could be defined.
Third party folks go off and write their svn plugin, etc. They develop
it as a statically linked module to the editor. When they're all done,
they release into the wild a library module intended to be statically
linked.

The editor, completely written in Go, of course, has a launching
sequence that goes something like this:

Checks a plugin directory folder to see if any new extension modules
installed, if so, invokes the linker to statically link up a new
program image. The launcher code then execs execution of the new
program image.

Naturally if the launcher had not detected any new modules and there
was no link phase to do, it would have directly execed the program
image.

Am presuming static linking would be fast enough that would never
annoy users whenever it happens.

Now this approach to a plugin architecture does not allow for
extension modules to be bound during program execution time. Any time
a new module gets added, there will be need for a relink and app
restart. Could folks live with that?

BTW, am assuming the extension modules will be making calls against
the host extension point APIs such that the static linker will see
these references and bind in the code of the extension module into the
host image.

Paulo Pinto

unread,
Jul 31, 2010, 1:47:59 PM7/31/10
to golang-nuts
I guess your approach requires that the "Eclipse" users would need to
access the plugins
to be able to compile+link all plugins.

Or at least some kind of linker, to be able to relink all modules.

For something like Eclipse, the only possible solution I see is to
have one Go process
per plugin, making use of process IPC to communicate.

Depending on the OS, this would be quite costly, or not.

If we use Eclipse as example, my current installation has 327 plugins.
Should we then
have so many processes running?

--
Paulo

Cory Mainwaring

unread,
Jul 31, 2010, 2:32:47 PM7/31/10
to Paulo Pinto, golang-nuts
I think the most efficient approach to a process IPC plugin architecture would be to have the plugins be like the little unix commands that are so useful: cat, ls, etc. It takes a data stream (presumably that it can define via the necessary configuration file) and outputs a modified version of that data stream. The program is only run when needed. Realtime plugins would have an issue with that, but most would be fine.

Dynamic loading still seems the best course of action for plugin architectures (since dynamic linking is evil). But that's yet to be implemented into Go. For now, recompilation has a pretty low cost, and most users wouldn't be offended by a startup that includes installing new plugins. Firefox does it to millions of users every day. And if they're users of an IDE, what's a few extra seconds waiting for it to open? I already clock my Eclipse at around 2 minutes to start up when I'm doing other stuff (1 minute for doing nothing), and Visual Studio 2008 at around 45 seconds. From what I hear, all of the packages in Go can be made in a few seconds, so I doubt an IDE would be too far over that. 

Russ Cox

unread,
Jul 31, 2010, 5:18:43 PM7/31/10
to Paulo Pinto, golang-nuts
> If we use Eclipse as example, my current installation has 327 plugins.
> Should we then have so many processes running?

Is that a problem? Processes aren't physical objects; they're just memory.

Russ

Clark Gaebel

unread,
Jul 31, 2010, 7:41:38 PM7/31/10
to golang-nuts
What if you used the netchan library and developed a local networking
protocol for the IDE? Then plugins run in their own processes,
communicating with the main "eclipse" through their networked
channels. This has the added benefit of a plugin never being able to
take down the main IDE.

Cory Mainwaring

unread,
Jul 31, 2010, 7:51:26 PM7/31/10
to Clark Gaebel, golang-nuts
still not great for tight integration (realtime pixel editing and the like)

Scott Lawrence

unread,
Jul 31, 2010, 8:07:35 PM7/31/10
to Clark Gaebel, golang-nuts

It wouldn't be able to take down the main IDE with any form of IPC,
although this is probably indeed the best way to do it (provided you
want them to be separate processes).

> still not great for tight integration (realtime pixel editing and the like)

If you're on linux, you're using IPC anyway via X. If you make a
decent protocol (and with netchan, that's pretty easy), things should
work smoothly.

--
Scott Lawrence

Scott Lawrence

unread,
Jul 31, 2010, 8:09:16 PM7/31/10
to Clark Gaebel, golang-nuts
(Sorry, I didn't mean to exclude bsd/minix/plan9 (in order of user
base size ;-) users with the "If you're on linux.")


--
Scott Lawrence

Clark Gaebel

unread,
Jul 31, 2010, 8:45:16 PM7/31/10
to Scott Lawrence, golang-nuts
"Linux" could probably have been replaced with "not windows". :)

--
Regards,
-Clark

Scott Lawrence

unread,
Jul 31, 2010, 8:55:37 PM7/31/10
to Clark Gaebel, golang-nuts
Well, eventually, go will probably have a native mac gui library. (I
dunno, maybe it already does?)


--
Scott Lawrence

Cory Mainwaring

unread,
Jul 31, 2010, 11:36:48 PM7/31/10
to Scott Lawrence, RogerV, golang-nuts
Yes, open source is better, but companies have a pretty difficult time letting go of knowledge rights, and thus open source will make Go less likely to be used in the business sector until dynamic loading occurs. Which is a :( for anyone who works in programming for a living and would like to see Go infiltrate their day-job. You know, just wishful thinking and all.

On 31 July 2010 23:29, Scott Lawrence <byt...@gmail.com> wrote:
On 7/31/10, RogerV <roger....@gmail.com> wrote:
> Agreed, a process per plugin would get unwieldy for something like
> Eclipse. Hence why was proposing to just statically link the plugins
> into the core program image of the host app, so would all run as one
> happy process.

Only for you. The computer doesn't really care.


On 7/31/10, Cory Mainwaring <olr...@gmail.com> wrote:
> Sounds like writing closed-source software would be difficult in this model,
> if not impossible.

Sounds like using this model would make writing closed-source software
difficult, if not impossible. Pity. (Like reverse 'tivoization'?)

</tongue-in-cheek> Well then, closed-source authors will just have to
use an alternate model until/unless go supports/decides-to-support
dynamic loading.


On 7/31/10, RogerV <roger....@gmail.com> wrote:
> Hence why I proposed to just take the approach of statically linking
> the so-called plugin modules to the core image of the host app - run
> everything in just one process and use goroutines for concurrency.

This has the disadvantage that catching and recovering from errors
-could be very difficult- is occasionally downright impossible.
Goroutines share memory. You can't expect your plugins to be
intelligent. If a plugin wanted to use cgo for some feature (an
entirely reasonable assumption, and something any decent
statically-linking plugin system should support), a small bug could
crash everything, despite the fact that the vast majority of the code
is written in a language without pointer arithmetic.

--
Scott Lawrence

Cory Mainwaring

unread,
Jul 31, 2010, 11:10:15 PM7/31/10
to RogerV, golang-nuts
Sounds like writing closed-source software would be difficult in this model, if not impossible.

On 31 July 2010 23:08, RogerV <roger....@gmail.com> wrote:
Well, every process represents a thread of execution that has to be
scheduled by the OS. Certainly more heavy weight that goroutines.


Hence why I proposed to just take the approach of statically linking
the so-called plugin modules to the core image of the host app - run
everything in just one process and use goroutines for concurrency.

Surely there's no problem in including the Go static linker with an
application's distribution...

chris dollin

unread,
Aug 1, 2010, 2:35:42 AM8/1/10
to Cory Mainwaring, RogerV, golang-nuts
On 1 August 2010 04:10, Cory Mainwaring <olr...@gmail.com> wrote:
> Sounds like writing closed-source software would be difficult in this model,
> if not impossible.

Plugins could be object files, yes?

Relinking doesn't mandate recompilation of the plugins, or most
of the core.

Chris

--
Chris "allusive" Dollin

RogerV

unread,
Jul 31, 2010, 11:04:02 PM7/31/10
to golang-nuts
On Jul 31, 10:47 am, Paulo Pinto <paulo.jpi...@gmail.com> wrote:
> I guess your approach requires that the "Eclipse" users would need to
> access the plugins
> to be able to compile+link all plugins.
>
> Or at least some kind of linker, to be able to relink all modules.
>

Yes, exactly, would include the Go static linker as part of the
application installation. Shouldn't be a problem to do that given it's
all open source.

> For something like Eclipse, the only possible solution I see is to
> have one Go process
> per plugin, making use of process IPC to communicate.
>
> Depending on the OS, this would be quite costly, or not.
>
> If we use Eclipse as example, my current installation has 327 plugins.
> Should we then
> have so many processes running?
>
> --
> Paulo

chris dollin

unread,
Aug 1, 2010, 2:31:00 AM8/1/10
to Paulo Pinto, golang-nuts
On 31 July 2010 18:47, Paulo Pinto <paulo....@gmail.com> wrote:
> I guess your approach requires that the "Eclipse" users would need to
> access the plugins
> to be able to compile+link all plugins.
>
> Or at least some kind of linker, to be able to relink all modules.

Ship 8(6)(whatever)l.

> For something like Eclipse, the only possible solution I see is to
> have one Go process
> per plugin, making use of process IPC to communicate.

Why? If we're linking a binary, we're done.

> Depending on the OS, this would be quite costly, or not.
>
> If we use Eclipse as example, my current installation has 327 plugins.
> Should we then have so many processes running?

I don't know abouit "should". "Could", perhaps. And "no need to."
Doing plugins by spawning processes is a different choice than
doing them by static linking.

Chris

[And relinking time only needs to compete with Eclipse startup
time, which is not exactly brief. Perhaps an incremental linker
so that some of the linking could be done in advance?]

RogerV

unread,
Jul 31, 2010, 11:08:11 PM7/31/10
to golang-nuts
On Jul 31, 2:18 pm, Russ Cox <r...@golang.org> wrote:

Scott Lawrence

unread,
Jul 31, 2010, 11:29:26 PM7/31/10
to RogerV, golang-nuts
On 7/31/10, RogerV <roger....@gmail.com> wrote:
> Agreed, a process per plugin would get unwieldy for something like
> Eclipse. Hence why was proposing to just statically link the plugins
> into the core program image of the host app, so would all run as one
> happy process.

Only for you. The computer doesn't really care.


On 7/31/10, Cory Mainwaring <olr...@gmail.com> wrote:
> Sounds like writing closed-source software would be difficult in this model,
> if not impossible.

Sounds like using this model would make writing closed-source software


difficult, if not impossible. Pity. (Like reverse 'tivoization'?)

</tongue-in-cheek> Well then, closed-source authors will just have to
use an alternate model until/unless go supports/decides-to-support
dynamic loading.


On 7/31/10, RogerV <roger....@gmail.com> wrote:

> Hence why I proposed to just take the approach of statically linking
> the so-called plugin modules to the core image of the host app - run
> everything in just one process and use goroutines for concurrency.

This has the disadvantage that catching and recovering from errors

Paulo Pinto

unread,
Aug 1, 2010, 8:50:09 AM8/1/10
to golang-nuts
Yes it is a big problem.

In most operating systems (I am excluding Unix variants here) processes are
heavy resources.

They take more time to do context switches, and in multicore environments
they may jump between cores, thus trashing their caches.

Besides the processes there is also the the other resources related to the
IPC (shared memory, semphores, mutexes, sockets) that might be required
for the communication.

So 327 process + IPC resources for one single application might just be too
much, depending on the target operating system.

--
Paulo

Paulo Pinto

unread,
Aug 1, 2010, 8:56:43 AM8/1/10
to golang-nuts
And that is the main reason why most graphic workstations nowadays are
Windows/Mac OS X based.

X cannot cope with the graphics performance that one expects from
certain types of applications.

--
Paulo

On Aug 1, 2:07 am, Scott Lawrence <byt...@gmail.com> wrote:

Cory Mainwaring

unread,
Aug 1, 2010, 9:13:28 AM8/1/10
to chris dollin, RogerV, golang-nuts
Doesn't one have to explicitly reference a package to have it be linked in?

David Roundy

unread,
Aug 1, 2010, 9:42:15 AM8/1/10
to RogerV, golang-nuts
On Sat, Jul 31, 2010 at 12:42 PM, RogerV <roger....@gmail.com> wrote:
> I've been wondering about this after following one of those
> discussions - could a viable "plugin" architecture for Go be built on
> the basis of its static linking approach?

For what it's worth, the approach you describe is what xmonad
(http://xmonad.org) uses for plugins. Xmonad itself is essentially a
library, and the configuration file can be a Haskell file, and there's
a little driver that will recompile the configuration file if needed,
or generate a default one if it's not present. Extending that to
automagically load plugins wouldn't be difficult.

You can also dynamically load plugins if you can serialize your
program state, which is what xmonad does.

David

RogerV

unread,
Aug 1, 2010, 10:57:16 AM8/1/10
to golang-nuts
On Jul 31, 11:35 pm, chris dollin <ehog.he...@googlemail.com> wrote:
> On 1 August 2010 04:10, Cory Mainwaring <olre...@gmail.com> wrote:
>
> > Sounds like writing closed-source software would be difficult in this model,
> > if not impossible.
>
> Plugins could be object files, yes?
>
> Relinking doesn't mandate recompilation of the plugins, or most
> of the core.
>
> Chris

Yes, my original proposal that started this particular thread presumed
that plugins would be compiled object files or static linkable
libraries consisting of object files.

Hence this particular concept would not mandate compiling original
source code and could be compatible with closed source development.

However, it would be necessary to work out some kind of bundle concept
where a bundle consist of different compiled versions of the plugin
supporting different target CPUs. Apple manages to pull this off with
their PowerPC/Intel application format for Mac OS X, so it's possible.

RogerV

unread,
Aug 1, 2010, 11:01:32 AM8/1/10
to golang-nuts


On Jul 31, 8:29 pm, Scott Lawrence <byt...@gmail.com> wrote:
>
> On 7/31/10, RogerV <roger.dewa...@gmail.com> wrote:
> This has the disadvantage that catching and recovering from errors
> -could be very difficult- is occasionally downright impossible.
> Goroutines share memory. You can't expect your plugins to be
> intelligent. If a plugin wanted to use cgo for some feature (an
> entirely reasonable assumption, and something any decent
> statically-linking plugin system should support), a small bug could
> crash everything, despite the fact that the vast majority of the code
> is written in a language without pointer arithmetic.
>
> --
> Scott Lawrence

Eclipse successfully runs all plugins in a single JVM process.

jimt

unread,
Aug 1, 2010, 11:02:54 AM8/1/10
to golang-nuts
The relinking approach does require that either the source code of the
main app is distributed with the program, or only the compiled object
files (.[ao]). Since the object files are easily reverse engineered,
it is practically the same as giving away the source. If you are
dealing with a closed source project, this may well not be an ideal
situation.

I've considered if it would be possible to perform a binary patch on
the compiled executable itself, but that would mean embedding the
entire plugin package itself into the binary. Static linking normally
only includes those parts of a package that are actually used. This
would mean your relinker has 2 options:

1) Figure out what parts are used, and embed only those.
2) Simply embed the entire plugin, presuming that since it's a plugin
designed for the main app, all of it will be used at some point.

The first one is more efficient in the long run. e.g.: potentially
smaller binary and thus smaller memory footprint.
Both of them require some additional work apart from embedding the
compiled plugin code into the app. You'll also have to modify the code
that actually interacts with the plugins to include the new one.

Considering all the potential pitfalls here, I personally doubt it's
worth it,. But perhaps someone with insight into binary patching can
shed some light on that.

On Aug 1, 3:42 pm, David Roundy <roun...@physics.oregonstate.edu>
wrote:

Clark Gaebel

unread,
Aug 1, 2010, 11:32:04 AM8/1/10
to golang-nuts
One thing which hasn't been mentioned yet is the GPL license.

If our only option is static linking, GPL'd code will create an
"island" that non-GPL code can't touch. I have a feeling that in the
end, the GPL license will never be used with Go code, and that's a
shame. It does have its uses.

David/Jones

unread,
Aug 1, 2010, 7:46:19 PM8/1/10
to golang-nuts


On 1 Aug., 05:08, RogerV <roger.dewa...@gmail.com> wrote:
> On Jul 31, 2:18 pm, Russ Cox <r...@golang.org> wrote:
>
> > > If we use Eclipse as example, my current installation has 327 plugins.
> > > Should we then have so many processes running?
>
> > Is that a problem?  Processes aren't physical objects; they're just memory.
>
> > Russ
>
> Well, every process represents a thread of execution that has to be
> scheduled by the OS. Certainly more heavy weight that goroutines.

I'm trying to figure how much more expensive processes are compared to
goroutines. For me as an unaware programmer, they seem very similar.
Until I figured that out, I support the IPC solution over the
relinking one.
I also think that removing/adding plugins dynamically would be
interesting. I'm thinking of a plugin manager similar to that of most
KDE software I've seen lately.

Best wishes, David

Scott Lawrence

unread,
Aug 1, 2010, 8:23:27 PM8/1/10
to RogerV, golang-nuts
On Sun, Aug 1, 2010 at 11:01, RogerV <roger....@gmail.com> wrote:
> Eclipse successfully runs all plugins in a single JVM process.

I'd debate the "successfully" there. (I have encountered plugins that
have caused problems.)

--
Scott Lawrence

RogerV

unread,
Aug 1, 2010, 9:28:32 PM8/1/10
to golang-nuts
On Aug 1, 4:46 pm, "David/Jones" <DaveyJon...@web.de> wrote:
> I'm trying to figure how much more expensive processes are compared to
> goroutines. For me as an unaware programmer, they seem very similar.
> Until I figured that out, I support the IPC solution over the
> relinking one.
> I also think that removing/adding plugins dynamically would be
> interesting. I'm thinking of a plugin manager similar to that of most
> KDE software I've seen lately.
>
> Best wishes, David

At least a couple of pages of memory (real memory) for the runtime
stack per each thread of execution that a process represents plus
address space for stack growth, code image, and heap zone. So, say, 2
pages is 8K and loading around 340 plugins, that's ~ 2.6 MB of RAM
consumed of overhead. That's really more of a calculation for just in-
proc threads. Processes would represent more overhead than that.

A Go program running all goroutines in a single process might get by
on just 2 to 4 threads, depending on, say, the number of cores the CPU
has.

Now Google Chrome does okay running multiple processes. I counted the
number of processes of Chrome I currently have running and it is 22.
There's one parent process that has spawned 21 child processes.

I will definitely concede that Chrome is a successful multi-process
architectural approach. The processes are not for running plugins per
se (excepting for Flash Player or Adblock plugins), though, and it's
not mounting up to hundreds of child processes.

The amount of virtual memory consumed by all these Chrome processes is
rather considerable (multi-gigabytes when aggregated). I'm running a
64-bit OS, though, so the address space consumption is not the problem
it would be in a 32 bit OS.

So on the one hand there is much about the Chrome architecture that
would suggest a multi-process approach to plugins could indeed be
viable. Whether it would scale to the level that Eclipse does plugins
(hundreds) - that is not as clear to see.

Nigel Tao

unread,
Aug 2, 2010, 4:18:10 AM8/2/10
to RogerV, golang-nuts
On 2 August 2010 11:28, RogerV <roger....@gmail.com> wrote:
> The amount of virtual memory consumed by all these Chrome processes is
> rather considerable (multi-gigabytes when aggregated).

Note that the total memory used by all these processes isn't
necessarily the naive sum of each process' consumption. The latter
tends to double-count shared resources.

http://sites.google.com/a/chromium.org/dev/memory-usage-backgrounder
has some more detail.

David Leimbach

unread,
Aug 2, 2010, 12:51:58 PM8/2/10
to golang-nuts
This does not make sense to me. People who like the GPL are going to
(and I think you mean the LGPL) are going to use it anyway, because
they like distributing code with a viral license, for the same reasons
that people who write BSD or MIT licensed code don't want a viral
license.

If Go is not capable of dynamic linking, that just factors out a given
set of rules for LGPL adherence, it does not preclude people from
licensing stuff with the GPL or LGPL.

Haskell has the same situation by the way, and developers are
discouraged from licensing libraries as LGPL or GPL because it limits
their overall usefulness to all members of the Haskell community. To
some people, the goal is to have those restrictions in place anyway,
as that's why the license was chosen.

Dave

David Leimbach

unread,
Aug 2, 2010, 12:56:50 PM8/2/10
to golang-nuts


On Aug 1, 4:46 pm, "David/Jones" <DaveyJon...@web.de> wrote:
> On 1 Aug., 05:08, RogerV <roger.dewa...@gmail.com> wrote:
>
> > On Jul 31, 2:18 pm, Russ Cox <r...@golang.org> wrote:
>
> > > > If we use Eclipse as example, my current installation has 327 plugins.
> > > > Should we then have so many processes running?
>
> > > Is that a problem?  Processes aren't physical objects; they're just memory.
>
> > > Russ
>
> > Well, every process represents a thread of execution that has to be
> > scheduled by the OS. Certainly more heavy weight that goroutines.
>
> I'm trying to figure how much more expensive processes are compared to
> goroutines. For me as an unaware programmer, they seem very similar.
> Until I figured that out, I support the IPC solution over the
> relinking one.

For goroutines you could look at the FAQ for the language design:

http://golang.org/doc/go_lang_faq.html#goroutines

As for processes, the cost of those will vary from OS to OS, as well
as the conditions under which they were created, and what
optimizations were implemented by the OS.

Paulo Pinto

unread,
Aug 2, 2010, 5:09:22 PM8/2/10
to golang-nuts
Only partially.

GHC 6.12.1 supports dynamic linking in Linux, and they are working to
add support for the remaining
platforms.

http://article.gmane.org/gmane.comp.lang.haskell.general/17678

--
Paulo

RogerV

unread,
Aug 2, 2010, 5:59:56 PM8/2/10
to golang-nuts
On Aug 2, 1:18 am, Nigel Tao <nigel.tao.gn...@gmail.com> wrote:
Thanks for that link, Nigel, that was some good reading.

I'm an avid Chrome user and I like its multi-process architectural
approach. I tend to agree with the section at that link that sites the
advantage of reclaiming memory and resources when closing a Chrome
tab. Exiting a process per that tab fully returns the memory back to
the system for reuse.

The Eclipse editor plugin scenario that I started this discussion
thread with would not be as dynamic in use of plugins as, say, a web
browser in visiting sites and loading tabs.

So Chrome is certainly inspirational in respect to conceiving of
taking a multi-process approach to plugins. Yet there's still the
matter of scaling to hundreds of plugins ala Eclipse.

On my 4 GB Linux computer I can comfortable run Chrome with 20 to 30
processes being active (taking into consideration some of the other
software I run typically at the same time). Yet when going beyond that
realm, Chrome causes my computer to fall over. So I don't think there
could be a viable plugin architecture that uses a process per plugin
where the host application is using hundreds of plugins. That
application is not likely to run very well on most end user computers.

David Roundy

unread,
Aug 3, 2010, 6:57:55 AM8/3/10
to RogerV, golang-nuts
On Mon, Aug 2, 2010 at 5:59 PM, RogerV <roger....@gmail.com> wrote:
> On my 4 GB Linux computer I can comfortable run Chrome with 20 to 30
> processes being active (taking into consideration some of the other
> software I run typically at the same time). Yet when going beyond that
> realm, Chrome causes my computer to fall over. So I don't think there
> could be a viable plugin architecture that uses a process per plugin
> where the host application is using hundreds of plugins. That
> application is not likely to run very well on most end user computers.

I doubt it's the number of processes that's causing the trouble but
rather the amount of memory used. On my computer, the chrome
processes have resident set sizes ranging from 12m to 246m, whereas
the "top" process I'm using to view memory use only uses 1.4m. Of
course, that's still reasonably bloated, and if you wrote your plugins
efficiently, they should take way under a megabyte of memory, and
running hundreds of them shouldn't be a problem.
--
David Roundy

Namegduf

unread,
Aug 3, 2010, 8:25:20 AM8/3/10
to golan...@googlegroups.com
On Tue, 3 Aug 2010 06:57:55 -0400
David Roundy <rou...@physics.oregonstate.edu> wrote:
> I doubt it's the number of processes that's causing the trouble but
> rather the amount of memory used. On my computer, the chrome
> processes have resident set sizes ranging from 12m to 246m, whereas
> the "top" process I'm using to view memory use only uses 1.4m. Of
> course, that's still reasonably bloated, and if you wrote your plugins
> efficiently, they should take way under a megabyte of memory, and
> running hundreds of them shouldn't be a problem.

Given that Hello World in Go uses about 700KB of RAM, I'm a little
dismayed that someone would claim that each process should use "way
under" a megabyte. Static linking makes a "many small processes"
approach somewhat more expensive, and this needs to be taken into
account.

Such an approach probably would take hundreds of megabytes on top of
the memory used elsewhere for the described scenario, and I wouldn't
precisely consider that "not a problem"; indeed, I find that it's been
written off as a concern so quickly rather alarming.

I'm open to solutions other than dynamic loading for writing modular,
live-upgradable software, and I think some others that have been
suggested could be okay, but if this idea was the best Go had to offer
for a "several hundred modules" scenario, I would personally write it in
C.

David Roundy

unread,
Aug 3, 2010, 9:55:02 AM8/3/10
to Namegduf, golan...@googlegroups.com
On Tue, Aug 3, 2010 at 8:25 AM, Namegduf <name...@googlemail.com> wrote:
> On Tue, 3 Aug 2010 06:57:55 -0400
> David Roundy <rou...@physics.oregonstate.edu> wrote:
>> I doubt it's the number of processes that's causing the trouble but
>> rather the amount of memory used.  On my computer, the chrome
>> processes have resident set sizes ranging from 12m to 246m, whereas
>> the "top" process I'm using to view memory use only uses 1.4m.  Of
>> course, that's still reasonably bloated, and if you wrote your plugins
>> efficiently, they should take way under a megabyte of memory, and
>> running hundreds of them shouldn't be a problem.
>
> Given that Hello World in Go uses about 700KB of RAM, I'm a little
> dismayed that someone would claim that each process should use "way
> under" a megabyte. Static linking makes a "many small processes"
> approach somewhat more expensive, and this needs to be taken into
> account.

Yikes! I hadn't paid attention to memory use of small go programs, and
that is pretty crazy! I knew that the binaries were a bit large, but
imagined that the entire executable wouldn't need to be loaded
immediately into memory.
--
David Roundy

Russ Cox

unread,
Aug 3, 2010, 1:53:48 PM8/3/10
to David Roundy, Namegduf, golan...@googlegroups.com
>> Given that Hello World in Go uses about 700KB of RAM, I'm a little
>> dismayed that someone would claim that each process should use "way
>> under" a megabyte. Static linking makes a "many small processes"
>> approach somewhat more expensive, and this needs to be taken into
>> account.
>
> Yikes! I hadn't paid attention to memory use of small go programs, and
> that is pretty crazy! I knew that the binaries were a bit large, but
> imagined that the entire executable wouldn't need to be loaded
> immediately into memory.

It's bigger than we'd like it to be, but it's competitive with C and C++.
If you run a hello world under /usr/bin/time on Linux, it prints
the number of page faults in the statistics. That's the most
reliable number I've found for measuring how much memory
the program actually used. On my Ubuntu 10.04 box, I get:

110 ( 451K) Go println("hello, world")
140 ( 573K) Go os.Stdout.WriteString("hello, world\n")
145 ( 594K) C printf("hello, world\n");
229 ( 938K) Go fmt.Println("hello, world")
313 (1282K) C++ cout << "hello, world\n";

I think the difference with fmt is that fmt imports unicode (indirectly),
and there are some initialized maps in that package that get
created at runtime. If the compiler could lay them out statically
in the data section, I think it would cut the memory usage down.
In fact if fmt.Println can't actually refer to them it would cut them
out of the binary entirely, which would be even better.
There's definitely room for improvement, but we're not doing too bad.
And if you pass in a nil pointer to fmt.Println you get a much
more useful failure than when you do that in C or C++.

Russ

RogerV

unread,
Aug 4, 2010, 12:38:05 AM8/4/10
to golang-nuts
Actually it's the static link approach to a plugin architecture that
would share the Go runtime overhead of the host app across all
plugins.

The plugin-as-a-process would be the architectural approach that would
incur the overhead of the Go runtime per each plugin - the 700 KB you
refer to for hello world.

And because each plugin would be its own unique program image there
wouldn't be an opportunity to leverage an OS fork() call that does
copy-on-write as a way to share that overhead.

On Aug 3, 5:25 am, Namegduf <nameg...@googlemail.com> wrote:
> On Tue, 3 Aug 2010 06:57:55 -0400
>

Cory Mainwaring

unread,
Aug 4, 2010, 12:42:58 AM8/4/10
to RogerV, golang-nuts
the Go runtime seems to be around 400k, with fmt adding 300k. So half a meg, instead of 3/4ths. Not much, but a big difference at scale.

jimmy frasche

unread,
Aug 4, 2010, 12:52:20 AM8/4/10
to RogerV, golang-nuts
If you use println or (for that matter an empty main) instead of
fmt.Println then 8.out is only 112k, with the latest release 8g.

Namegduf

unread,
Aug 4, 2010, 2:22:15 AM8/4/10
to golan...@googlegroups.com
On Wed, 4 Aug 2010 00:42:58 -0400
Cory Mainwaring <olr...@gmail.com> wrote:

> the Go runtime seems to be around 400k, with fmt adding 300k. So half
> a meg, instead of 3/4ths. Not much, but a big difference at scale.

Working without fmt would mean lacking fmt.Fprintf() and Sprintf() and
the rest while working with IPC; if you're communicating over a
socket or pipe, that seems rather a pain. I thought fmt was actually a
nice example of a module you would be likely to need.

You would also need all other packages needed for whatever your
approach to IPC was, and all packages related to what the module was
actually doing, and internal packages of your program for its types and
functions (likely including an IPC wrapper?), any or all of which could
be significant in size.

All in all, I don't think the plugins being the minimum possible size
for a Go program is likely, even if fmt could be avoided.

Alexander Surma

unread,
Aug 4, 2010, 4:17:51 AM8/4/10
to golan...@googlegroups.com
> Working without fmt would mean lacking fmt.Fprintf() and Sprintf() and
> the rest while working with IPC; if you're communicating over a
> socket or pipe, that seems rather a pain.

You really wanna do IPC with fmt? I thought we were talking rpc package.

Namegduf

unread,
Aug 4, 2010, 4:29:08 AM8/4/10
to golan...@googlegroups.com

The rpc package imports gob, which imports fmt.

David Leimbach

unread,
Aug 4, 2010, 11:00:15 AM8/4/10
to golang-nuts
So why not an explicit loader (not shared library dynamic linking)?

You could fork a main process, then load your plugin. The main
application could be as little as a fork and loader :-).

Then you might be able to get your copy-on-write optimization if the
kernel implements it for forked processes.

Those forked processes could still use IPC, and the shared text
segments wouldn't incur a lot of overhead (hopefully).

Dave
Reply all
Reply to author
Forward
0 new messages