Is this expected behaviour?
The GC is limited to taking about 25% of the available CPU, so giving
it more goroutines just gives it more of a chance to look for
non-existent garbage.
I'm CC'ing austin so that he can tell me if I'm completely wrong.
The GC is limited to taking about 25% of the available CPU, so giving
it more goroutines just gives it more of a chance to look for
non-existent garbage.
I'm CC'ing austin so that he can tell me if I'm completely wrong.
I think I would be better off if I had control over the GC. Specifically, if I could turn off automatic GC and pick when and where (i.e. in a goroutine pinned to an OS thread) I did it. That would stop the background CPU consumption. I'm better off with a 100 ms stall than the high CPU consumption.
You can control GC in an important sense, especially in the cyclic application you describe. Manage your own pool of objects that the tree is build from. Put your allocator in there, with a free list, and a recycle logic for “free” activities. This way the total memory use is no more than two trees, or 1 plus the fraction of the old tree that you can release as you process it in parallel with building a new one.
I do this all the time and essentially have GB of data in play with nearly zero garbage creation until the program finishes. (Nearly zero but not zero because of miscellaneous non-pool allocations and certain anti-memory-waste strategies.) It is simple and fast.
Oh, sorry. Set GOGC=off. (The value used inside the runtime is -1, but, in fact, GOGC=-1 will set the internal value to 0, just as you saw. :)
In each cycle, is 99% of the new tree the same as the old tree?
On Fri, 02 Oct 2015 09:30:29 PDT Richard Gooch <rg+go...@safe-mbox.com> wrote:
>
> I think that approach will still leave a lot of work for the GC because I
> allocate a lot of slices (directory entries). I'd need to implement a slab
> allocator for the different slice lengths. This doesn't sound easy anymore
> :-/
So a slice holds directory entries and you append to it one at
a time? Can you create a slice with a much larger capacity
and then trim?
From quickly scanning this thread, looks like you are
repeatedly doing the equivalent of "find / ..." on a
filesystem. If you can explain in some detail what youre code
does, we might be able to provide more specific suggestions.
There is more than one way to skin a cat (or "find" in this
case:)
Maybe try Readdir in a loop limiting the slice size. (Readdir names also sorts, but that is not much work)
Generally: don't create garbage, reuse everything!
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Filesystem notification seems a natural way here.
Oh, sorry. Set GOGC=off. (The value used inside the runtime is -1, but, in fact, GOGC=-1 will set the internal value to 0, just as you saw. :)
Why do you pin walking goroutine? Why don't you parallelize walk by natural way (i.e. goroutine per thread with some kind of concurrency limit).
Good suggestion. On that front, I wrote a parallel version of the standard filesystem walker last year. Maybe something like this would be of interest to Richard once he gets his design for memory reuse solved:
https://groups.google.com/forum/#!searchin/golang-nuts/walk$20jones$20parallel/golang-nuts/FplDIeViOq4/dFctpG5MS-kJ
…note that it’s is often 10x faster (scroll to last post) and one of the sample programs (dup at https://github.com/MichaelTJones) does a nice hierarchical job of testing for sameness.
This might be helpful, on Linux: http://man7.org/linux/man-pages/man7/fanotify.7.html
What happens, if you set GOMAXPROCS(1)?
More general question to core team: is locked thread encounted in GOMAXPROCS?
--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/YaRDry8ZCYk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
What do you mean "the kernel doesn't know about"? Is there such thing?
Except hardware errors, all fs access goes through the kernel, so it does know about.
I call Readdirnames(), then I walk the directory entries, call syscall.Lstat() and add each entry to one of 4 slices, depending on whether it's a regular file, symlink, device node/pipe or a directory.
What I used to do was create each of those slices with capacity = num dirents, but that of course wastes memory, as I mentioned above. The next thing I did was to allocate new slices of the correct length for each type and deref the oversized slices. That brought down allocated memory (after a GC()) but pushed up Sys memory consumption. So I gave up on that and just leave it up to append() to decide how much memory to allocate.
As I mentioned upthread, I've considered just creating a slice of interface{} and sticking the different entry types in there, but I've been concerned that will have a performance cost since I'll need a bunch of type switches all over. I don't have enough experience with benchmarking Go to know if that's a concern, but it's work I was hoping to avoid (or at least defer:-). Somebody who knows please feel free to speak up now :-)
What happens, if you set GOMAXPROCS(1)
On Sunday, 4 October 2015 22:15:24 UTC-7, Sokolov Yura wrote:What happens, if you set GOMAXPROCS(1)
I get the pinned (niced) OS thread, and 1-2 "main" OS threads. However, the aggregate CPU time is ~100% of one core. So, even though there are still multiple OS threads running, only one at a time seems to run. Which is good enough for my purposes.