Even then you may not want to do that, due to battery concerns.
On Fri, Aug 13, 2010 at 2:06 PM, Brian Carper <brian...@gmail.com> wrote:
> Do you plan to share the source code? Any reason you went with Swing
> instead of OpenGL?
>
--
Omnem crede diem tibi diluxisse supremum.
This can be made a bit better by turning Escape Analysis on? Have you
tried that?
The G1 collector is supposed to have lower latency. Have you tried it?
(GC choice/tuning is a loooong story, but some select suggestions follow)
First off, make sure you're at least using CMS
(-XX:+UseConcMarkSweepGC) or G1 at all to begin with - the default
collector is the throughput collector which will always do full GC:s
of the old generation so that you are guaranteed to get pause times
that scale linearly with heap size (unless you're generating *zero*
non-young garbage).
With CMS, you can force shorter young generation pauses by limiting
the size of the young generation (usually at the cost of more GC work
in total; i.e., less throughput, because the older generation is more
expensive to collect). I'm not sure at all how much control over VM
options you have with Java WebStart though, but in general that would
be my suggestion if the young generation pauses are too long.
-XX:NewSize=SIZE and -XX:MaxNewSize=SIZE should be your friend here
(and -XX:+UseParNewGC though I think that is always the default on
modern VM:s anyway on multi-core machines). I'm making the assumption
here that the allocation pattern is not such that the concurrent
mark/sweep:s are the problem.
With G1, you can directly specify target pause times that G1 tends to
be pretty good at maintaining in my experience. A recurring issue for
me and at least some others seems to be that your application may have
a workload that disallows certain memory regions to be collected
within the pause time goal; this can lead to a build-up of
uncollectable regions that may eventually cause a fallback to a full
stop-the-world GC. The likelyhood of this happening is higher the
lower the pause time goal you specify. An starter command line to play
with (preferably with jdk 1.7) might be:
-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC
-XX:MaxGCPauseMillis=15 -XX:GCPauseIntervalMillis=20
--
/ Peter Schuller
his "Artificial Intelligence: A Modern Approach" is also a good book
if you are interested in game AI. 3rd edition just came out recently
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
We don't use Penumbra. On Java, we use JOGL, and on
other targets we use pure OpenGL or OpenGL ES API
for both compatibility and performance reasons. We have to ensure
whatever OpenGL stuff we do, will work everywhere.
>
> What do you mean by "battery concerns"?
Laptops, Mobile devices and such. If you use OpenGL on a laptop,
it will use the GPU assuming it's hardware accelerated. GPU is a big
battery drain. On mobile devices such as iPhone and Android, it's
even more so. Using OpenGL unnecessarily causes battery drain
on your hardware.
Plus, if you use OpenGL, and your target is using those Intel Extreme Graphics,
where the only thing it's Extreme at, is Extremely slow. :) You end up gain
nothing but lose lots.
Though I didn't write that paragraph, I have faced the same issue.
Suppose I have two functions in the same file, and one depends on the other:
(defn foo [x] (+ 1 x))
(defn bar [x] (* 2 (foo x)))
I can't switch their order without adding extra forward-declaration
code, which is redundant:
(declare foo)
(defn bar [x] (* 2 (foo x)))
(defn foo [x] (+ 1 x))
This example is just a minor irritation, that I need to make sure all
the functions in a file are in the right order.
A bigger problem is when the two functions are in different
files/packages. Suppose I have files a.clj and b.clj and place some of
my functions in each of those files based on some arbitrary
categorization that makes intuitive sense to me. Then I realize that
some of the functions in a.clj depend on some functions in b.clj,
while some functions in b.clj depend on some functions in a.clj. Can I
still use declare to resolve this circular dependency? Can I even
"require" a.clj from b.clj when I have already "require"d b.clj from
a.clj?
My solution so far has been to make sure that dependencies between
packages are never two-way. I deliberately choose categorizations that
won't result in circular dependencies between packages. I would much
prefer to just refer to whatever function I wish, from whichever
function I wish, and not need to think about which packages I am
allowed to depend on or in what order functions must appear in a file.
(def g) ;creates a var g that is unbound
(defn f []
(g)) ;ok
(defn g [] ;f will call this
nil)
as shown by Rich at
http://markmail.org/message/vuzvdr4xyxx53hwr#query:+page:1+mid:tzsd3k6tvvc4ahoq+state:results
On Fri, Aug 13, 2010 at 11:49 PM, Eric Lavigne <lavign...@gmail.com> wrote:
> Suppose I have two functions in the same file, and one depends on the other:
>
> (defn foo [x] (+ 1 x))
> (defn bar [x] (* 2 (foo x)))
>
> I can't switch their order without adding extra forward-declaration
> code, which is redundant:
>
> (declare foo)
> (defn bar [x] (* 2 (foo x)))
> (defn foo [x] (+ 1 x))
>
--
I discussed two problems. The first problem, which you addressed, was
mostly just a warm-up for discussing a related problem that is more
severe. Where can I put (def g) so that two files can "require" each
other?
This is not a rare problem for me. Like Mike Anderson, I work around
it by putting extra thought into which package-level dependencies I
will allow, which sometimes necessitates creating more or fewer
packages than I otherwise would have created.
Tim Daly
In your code, how many files/name spaces are you creating?
And how many lines of code are in each file? I'm curious how you
organize your code.
Me three. I find it to be a *lot* of work to avoid circular dependencies.
If I need to mutually defined types...
(declare new-a)
(deftype B....
... (new-a)...))
(deftype A)
(defn new-a [] (A.))
math (11 definitions, 80 lines)
matching (5 definitions, 54 lines)
units (2 definitions, 15 lines)
io (7 definitions, 74 lines)
physics (4 definitions, 28 lines)
metrics (7 definitions, 174 lines)
main (1 definition, 35 lines)
I originally wanted to include the contents of the units file in the
physics file, but then there would be a circular dependency between
physics and io. The io code needs to interpret half-life values in
files that provide information about isotopes, and those half-life
values are meaningless if you don't know the relationship between
seconds, hours, and years. Physics code needs access to io code quite
frequently because, for example, you can't determine what portion of
photons will penetrate a 1/4" thick iron plate without reading iron's
transmission coefficients as a function of photon energy from a file.
It's not a big deal to have a units package, but I don't typically
create a new category for just two definitions that already fit well
in one of the existing categories.
Also, there were two functions in the physics package that I moved to
the math package so that functions in the io package could depend on
them. These functions were responsible for sorting emission lines by
energy and filtering out emission lines that would not be included in
the analysis because their energies are often associated with false
positives. These operations need to be performed on every isotope that
is read from the application's isotope library, and the easiest way to
arrange that is to call them from the function that reads the isotope
library. Again, not a big deal, but I would not ordinarily include
code in the math package that can only operate on emission data - that
belongs in physics.
I originally wanted to include the contents of the units file in the
physics file, but then there would be a circular dependency between
physics and io.
Avoiding circular dependencies can result in either:
a) Everything ends up in one file.
b) Everything ends up in zillions of small files with very complex
dependency structures (and every time you move a function from one
namespace to another to avoid a circular dependency, you have to
locate every file that uses the relocated function and change the
references to that function, all without the help of IDEs that do this
kind of refactoring for you -- it can be a lot of work).
Both of these scenarios result in their own significant
maintainability problems. I think it's much more ideal to be able to
divide modules of functions into the appropriate granularity for the
task at hand. I have found that for some tasks, circular dependencies
arise very naturally at the desired level of granularity, and I don't
like having to rework everything into something that avoids circular
dependencies. This problem seems to be especially acute in rapidly
evolving systems, because you're forced to constantly think about
conforming to an acyclic structure at a time when you're focusing on
something other than overall structure. I'd rather get things to
work, and *then* when the code base becomes stable, figure out a more
optimal organization.
Sometimes there's simply no way around it. For instance, I recently
had some python code that (stripped to its simplest form) had two
classes, Document and Attachment, where Attachment was a specialised
subclass of Document, but Document had a list of Attachments as one of
its members. There was no way around packing the Document and
Attachment classes into one big file, simply because I couldn't do
circular module dependencies (python files are modules), but any
refactoring of the code to remove the circular dependency left it
*more* complicated than before.
martin
In Clojure, a protocol Attachable, could have been made explaining
what are the things you need for an attachment.
How would that have helped? The problem lay in the fact that there
could be many subclasses of Document, but only one specific subclass,
Attachment, could go into the attachments[] field. So if we had to
split the code into two files, we'd have
class Attachment(Document) # <-- attachment.py needs to import from document.py
...
and
class Document
def create_attachment
self.attachments += Attachment.new() # <-- document.py needs to
import from attachment.py
I did think for a while that it was a code smell, but after some
attempts at refactoring decided it was a "genuine" circular reference
in that this was the conceptually simplest and clearest way to write
it.
martin
Escape Analysis and GC tweeking does not need to change your code.
It is activated by option to the JVM.
It would be interesting to try it on your computer and if some options
helps really a lot,
dynamically detect if they are available in a launch script.
For the allocations of points in return values, macro can probably
helps a bit with the inlining,
it would be fun to throw one or two examples on the list to see if
there is a pattern.
I wouldn't advocate this solution if Escape Analysis removes the
problem, though.
Best,
Nicolas.
It's often helpful to have one component that acts as a message bus
between the other components.
A quick and dirty example:
;;; --------------------------------------------------
;;; The message bus
(ns game.event)
;; A map storing the functions that should be called when an event
;; occurs
(def callbacks (atom {}))
;; Functions for subscribing to, and dispatching events
(defn call-when [event callback]
...)
(defn dispatch [event & args]
...)
;;; --------------------------------------------------
;;; User interface
(ns game.ui
(:require [game.event :as event]))
;; An example of an event listener
(event/when :unit-destroyed
(fn [unit]
(comment Update the UI here)))
;; An example of an event dispatcher. Sends an event to be handled by
;; the component whose responsibility it is. Note that at this point
;; we don't know which component that is.
(defn request-reinforcements-button-clicked []
(let [amount (.getValue reinforcements-amount-input-field)]
(event/dispatch :reinforcements-requested amount)))
;;; --------------------------------------------------
I've found this approach to work quite well in game development. As
the components don't care about who reacts to the messages they send,
or who sent the messages they are interested in, it's very easy to
plug in and remove components as needed. For example, you can add a
sound component that plays appropriate sounds when events occur in the
game without requiring any changes to any other components.
This approach is especially helpful when unit testing. You can create
a new bus and plug in just the component under test, and then simulate
all the other components by sending the same messages as they do.
--
Timo
I stumbled across this implementation of alpha-beta in clojure on github:
http://github.com/rcrr/reversi/blob/master/strategies.clj#L251-282
It is a re-write of PAIP's CL version. (I didn't write it- just found it.)
-Ben
sometimes these algorithms are easier to implement by constructing an
infinite lazy trees of all the game, and
then independently writing a few strategy to explore the tree.
John Hughes gives an example of that in Section 5 of "Why functional
programming matters", that can be found on the internet.
If it can be done that way, this is nice has it separates the tree
construction, which is about the rule of the game, from the
evaluation/exploration part.
(defmacro top-down [ & body ]
`(do ~@(reverse body)))
then
(defn utility-fn [])
(defn high-level-fn [] (utility-fn))
becomes
(top-down
(defn high-level-fn [] (utility-fn))
(defn utility-fn [])
)
:)
2010/8/14 Btsai <benny...@gmail.com>:
What python allows to break the circular dependency is function-level imports:
attachment.py:
from document import Document
class Attachment(Document):
pass
document.py:
class Document(object):
def create_attachment(self):
from attachment import Attachment
self.attachments += Attachment.new()
I don't think clojure has anything like this; it looks like imports
are at the file-level, rather than the function level as in python.
Perhaps there is a way though?