/srv/irclogs.ubuntu.com/2012/12/13/#juju-dev.txt

davecheneybzr: ERROR: Cannot lock LockDir(chroot-93404944:///%2Bbranch/gocheck/.bzr/branch/lock): Transport operation not possible: readonly transport05:09
davecheney^ any ideas ?05:09
davecheneyscrew it, hit it with the rm hammer05:12
davecheneynope05:13
davecheneythat hasn't worked either05:14
wallyworld_davecheney: i've not seen that issue before, sorry, i'll see if i can find out05:24
wallyworld_davecheney: actually, it aappears to be because you may not have write permissions to the gocheck project codebase?05:26
davecheneywallyworld_: yeah05:27
davecheneyi guess I havent' submitted anything to that previously05:27
davecheneyi've written to gustavo05:27
wallyworld_nice easy error message :-)05:27
TheMueMorning06:40
Arammorning.09:45
TheMueAram: Hi09:47
jamhi aram and TheMue09:48
TheMuejam: Heya09:48
rogpeppemornin' all09:55
TheMuerogpeppe: Morning10:04
TheMueAnyone interested in reviewing the Firewaller 2.0? ;) https://codereview.appspot.com/6875053/10:05
dimiternrogpeppe, TheMue: morning10:06
TheMuedimitern: Hello10:06
rogpeppeTheMue: i'm having a look10:20
TheMuerogpeppe: Great, thanks.10:20
rogpeppeTheMue: line 184: copy(ports, unitd.ports)10:25
rogpeppeTheMue: how can that ever work?10:25
rogpeppeTheMue: because ports is a zero length slice10:25
TheMuerogpeppe: Oh, funnily it works. Have to look into copy().10:27
rogpeppeTheMue: it can't do - it will never copy any elements10:28
rogpeppeTheMue: so unitd.watchLoop will always be started with no ports10:28
TheMuerogpeppe: Good catch, will change.10:28
rogpeppeTheMue: make a test that fails before making the change10:29
TheMuerogpeppe: Any idea on how that test should look like?10:30
rogpeppeTheMue: i haven't looked too deeply, but the question is: why do you start watchLoop with some ports? does it make any difference to the externally visible semantics?10:31
rogpeppeTheMue: if it doesn't make a difference, maybe you should just pass nil to watchLoop and delete those two lines10:31
TheMuerogpeppe: Has been the result of longer discussions to do every startup with the current state.10:32
rogpeppeTheMue: so i guess it'll just set the same ports twice, right?10:33
TheMueRuetobas: Pardon?10:34
TheMueOops10:34
TheMuerogpeppe: ???10:34
TheMuerogpeppe: Passing them to the watchLoop() just avoids a first change event.10:35
rogpeppeTheMue: that's what i mean. won't that first change event trigger a redundant setting of the ports? (i actually meant "i guess it'll just set the ports redundantly")10:36
TheMuerogpeppe: Yes, it would do so.10:37
rogpeppeTheMue: hmm, and because you don't see environment port-setting events directly, you can't observe the difference10:38
TheMuerogpeppe: It's job of the both reconcileXyz() methods to compare the initial state with that of the environment or the instances. And then needed changes are done.10:40
TheMuerogpeppe: Everything later is then based on change events.10:41
TheMuerogpeppe: And the initial state is taken from the first events of the regarding watchers.10:41
rogpeppeTheMue: yes, that all seems fine. i was just wondering on whether it was possible to test that broken code.10:42
TheMuerogpeppe: With exporting internal states of the firewaller maybe. But I don't think it's worth it, your capture has been great and it would only demonstrate that you're right. :D10:44
=== asavu is now known as asavu_
=== asavu_ is now known as asavu
niemeyerGOod morning juju-devs11:40
TheMueniemeyer: Hiya11:41
dimiternniemeyer: morning :)11:42
rogpeppeniemeyer: yo!11:42
TheMueLunchtime, BIAB12:08
TheMueniemeyer: ping13:20
niemeyerTheMue: Hey13:20
TheMueniemeyer: Hi, could you please take a look at https://bugs.launchpad.net/juju-core/+bug/1084867 which Mark assigned to me yesterday.13:21
_mup_Bug #1084867: conn: conn connections should pause between retry attempts <juju-core:New for themue> < https://launchpad.net/bugs/1084867 >13:21
TheMueniemeyer: It's in state.Open() and I've got a question. Regarding mgo.13:21
TheMueniemeyer: If I'm right mgo.DialWithInfo() uses a func for dialing, but the timing if it's failing is controlled inside the method. You only may specify a timeout (here 10 minutes). Am I right?13:23
niemeyerTheMue: Where are the messages in that bug being printed?13:24
niemeyerTheMue: That code must necessarily be repeated for the message printing to be repeated, right?13:24
TheMueniemeyer: In the func passed to DialWithInfo()13:24
TheMueniemeyer: Yes, until the conn is established or the timeout happens.13:25
TheMueniemeyer: Is there a fixed time between those retries?13:26
niemeyerTheMue: There are retries, there are timeouts, there are delays13:28
TheMueniemeyer: Yes. IMHO Dave recomments a kind of exponential delay behavior. Alternatively to static delays.13:30
TheMueniemeyer: But maybe I misunderstand the comment.13:30
niemeyerTheMue: Yes, I can see in the bug that he recommends that13:30
niemeyerTheMue: Where is the repetition happening, for how long does it repeat quickly, how long does it wait until the quick repetitions?13:31
TheMueniemeyer: Sorry, no more details so far than written in the issue. So I'll try to talk to Dave tomorrow morning. Just wanted to know first if I'm missing something about the mgo dialing behavior.13:34
niemeyerTheMue: You don't have to talk to Dave, you have to understand the problem instead13:34
TheMueniemeyer: And will start some test runs here.13:34
niemeyerTheMue: Sorry, I definitely don't intend to sound harsh, but you have to do your home work when a bug is assigned to you13:34
TheMueniemeyer: No problem.13:35
niemeyerTheMue: This sounds like a trivial problem of a missing delay in the right place13:36
TheMueniemeyer: This would have been the next where I would have talked to you about. Such a kind of delay is possible in the dial func, but it may also be interesting for you as the creator of mgo to make it configurable via DialInfo in a next release.13:38
niemeyerTheMue: Where is the repetition happening? Who's dialing so quickly?13:39
niemeyerTheMue: You seem to have no idea13:39
niemeyerTheMue: Putting sleeps in the code when you have no idea about exactly how work is taking place is a terrible plan13:39
niemeyerTheMue: It can be in mgo, it can be in Open, it can be in the call site of Open, etc13:40
niemeyerTheMue: You have the whole code base at your hand13:40
TheMueniemeyer: It looks to me that the dial func passed to DialWithInfo() is repeated quickly. Am I right? It contains no own loop. And it is passed to DialWithInfo with the DialInfo.13:41
niemeyerTheMue: Exactly.. it contains no loop.. things that contain no loop do not lead to repetition13:42
niemeyerTheMue: How can it possibly be repeated?13:42
niemeyerTheMue: Staring at it and wondering how to control repetition is going to be ineffective13:42
TheMueniemeyer: It returns an error and no connection, so DWI() retries.13:42
niemeyerTheMue: Where?13:43
TheMueniemeyer: Aaargh, I think I've got it.13:44
TheMueniemeyer: I'm currently walking the call tree upwards.13:46
TheMueniemeyer: Have been too fixed on that Open().13:46
niemeyerTheMue: Don't guess.. put debug statements in, watch the timings, watch call traces13:46
TheMueniemeyer: Yes, will do so.13:47
niemeyerThree branches off the queue.. 10 to go14:40
niemeyerLunch first, though14:40
niemeyerrogpeppe2: https://codereview.appspot.com/6902070/ is reviewed16:06
niemeyerrogpeppe2: Either I'm on crack, or the logic there isn't entirely sound16:06
=== rogpeppe2 is now known as rogpeppe
rogpeppeniemeyer: you may well be right. let me check.16:06
rogpeppeniemeyer: the first add is because we can't do an add before the websocket handler function is invoked16:07
rogpeppeniemeyer: the websocket handler uses a different goroutine for each call (like the http server)16:08
niemeyerrogpeppe: Yeah, even then it doesn't seem entirely okay16:09
niemeyerrogpeppe: There are four different goroutines there16:09
niemeyerrogpeppe: With adds all around16:10
niemeyerrogpeppe: and it's not clear why16:10
niemeyerrogpeppe: There is also a channel blocking at the end of each handled connection, which also doesn't sound okay16:10
rogpeppeniemeyer: we need to wait until everything has cleaned up before dying16:10
niemeyerrogpeppe: We need to do a lot of things16:10
niemeyerrogpeppe: But that doesnt' mean we need a new goroutine for each one of those things16:11
rogpeppeniemeyer: i'm not sure how to avoid the goroutines16:11
niemeyerrogpeppe: I suggest starting from the principle that you don't need them, rather than from the principle that you do need them16:11
rogpeppeniemeyer: the only way to get the http listener to quit is to close its Listener16:12
niemeyerrogpeppe: Also note how run(lis) never returns an error, despite the fact it has an error return.. which means the outside goroutine, doing a Kill, never does it16:12
niemeyerrogpeppe: There's surprisingly little logic for that ton of logic16:12
rogpeppeniemeyer: yes, run never returns an error, because the error that it almost always gets is "use of closed listener"16:13
rogpeppeniemeyer: (if we used the error from http.Serve, that is)16:13
niemeyerrogpeppe: Sorry, I'm not sure I understand what you mean16:14
rogpeppeniemeyer: what error could Server.run return?16:14
niemeyerrogpeppe: Things that never return an error should not have an error return, and the error return from things that never return an error should not be used16:14
niemeyerrogpeppe: Both of these are false16:14
niemeyerIn the branch16:14
rogpeppeniemeyer: that's true. i should probably remove the error return from run16:14
niemeyerrogpeppe: Yes, that's a start16:14
niemeyerrogpeppe: What about that blocking channel at the end of every single handled connection?16:17
rogpeppeniemeyer: hmm, yes, that does seem a bit crackful16:18
rogpeppeniemeyer: i think it needs to be a select16:18
rogpeppeniemeyer: and wait for the st.run() to finish as well as the dying tomb16:19
niemeyerrogpeppe: Why? Why do we have a goroutine being created within the per-connection goroutine?16:19
rogpeppeniemeyer: i'm not sure i can use any less goroutines though16:19
rogpeppeniemeyer: because we need somewhere to wait for the dying tomb16:19
rogpeppeniemeyer: so that we can kill the connection16:20
niemeyerrogpeppe: One of the reasons why we have a tomb is precisely to not shut the door on running logic16:20
rogpeppeniemeyer: we're not shutting the door on running logic, we're waiting for websocket.JSON.Receive to receive an EOF, and quit the run loop16:21
rogpeppeniemeyer: that's the only way to terminate that run loop AFAIK16:21
niemeyerrogpeppe: That's not what conn.Close does16:21
rogpeppeniemeyer: what does it do?16:21
niemeyerrogpeppe: It closes the connection, doesn't it?16:22
niemeyerrogpeppe: Irrespective of whatever is going on within the goroutine16:22
rogpeppeniemeyer: yes. hmm, that will stop replies being sent, yesah16:22
rogpeppeniemeyer: there probably needs to be something so that we can tell when the message receiver is blocked on a message receive.16:24
rogpeppeniemeyer: (pity we can't half-close the connection)16:24
rogpeppeniemeyer: perhaps before it does a message receive, it could send the connection to another goroutine which will close it if it sees Dying.16:26
rogpeppeniemeyer: once it's got the message, it can ask for the connection back again16:27
rogpeppeniemeyer: it would still be the same number of goroutines, but the receiver would be more in control.16:28
niemeyerrogpeppe: The point isn't closing, I think.. the point is stopping and returning.. Close can be deferred on spot16:30
niemeyerfunc(conn ...) {16:31
niemeyer    defer conn.Close()16:31
niemeyer}16:31
rogpeppeniemeyer: the loop in run is blocked on receive. someone calls Server.Stop. how do we stop the run loop?16:31
niemeyerrogpeppe: Exactly..16:31
niemeyerrogpeppe: That's the issue we must solve: how to stop and return.. that decision must be taken with context, unlike what's being done right now16:32
rogpeppeniemeyer: i think closing the conn is the only way to do that16:32
rogpeppeniemeyer: but you're right that it shouldn't be done outside of run16:32
niemeyerrogpeppe: Of course not.. that's taking a cheap route from outside to knock logic we don't control down16:32
rogpeppeniemeyer: ok, so how do we get the run loop to unblock, if we can't close the conn?16:33
niemeyerrogpeppe: "if we can't close the Conn" is a red-herring16:34
niemeyerrogpeppe: Where would you close the Conn?  That's where you get the loop to unblock16:34
niemeyerrogpeppe: You don't want to close the Conn without context16:35
rogpeppeniemeyer: we need to close the conn *somewhere* right?16:35
niemeyer<niemeyer> rogpeppe: The point isn't closing, I think.. the point is stopping and returning.. Close can be deferred on spot16:35
niemeyer<niemeyer> func(conn ...) {16:35
niemeyer<niemeyer>     defer conn.Close()16:35
niemeyerrogpeppe: That's where you close the Conn16:35
rogpeppeniemeyer: i don't understand that code without further context16:35
niemeyerrogpeppe: handler := websocket.Handler(func(conn *websocket.Conn) { defer conn.Close()16:36
niemeyerrogpeppe: The connection must be closed when the handler is done running16:36
niemeyerrogpeppe: We don't close the connection to interrupt.. we interrupt to close the connection16:37
rogpeppeniemeyer: how can that work? the handler blocks receiving a message. if it's blocked receiving a message, how can it know that the server has been killed?16:37
niemeyerrogpeppe: That's the right question16:37
niemeyerrogpeppe: Answering it is what we must find out16:37
rogpeppeniemeyer: we could receive messages in a separate goroutine16:38
niemeyerrogpeppe: That's not solving the problem16:38
rogpeppeniemeyer: (that's still the same number of goroutines though)16:38
rogpeppeniemeyer: isn't it?16:38
niemeyerrogpeppe: We can have 10 goroutines.. we still must find a way to interrupt in the right spot16:38
rogpeppeniemeyer: i mean we could read messages in a goroutine, and send them on a channel.16:38
rogpeppeniemeyer: then select on that channel and Dying.16:39
niemeyerrogpeppe: It's not.. you're saying "we can move the problem to a separate goroutine".. surely we can. The problem is still in the other goroutine, though.16:39
rogpeppeniemeyer: we can't do it with one goroutine. period.16:39
niemeyerrogpeppe: That's an irrelevant invariant.. we should look for the solution, rather than how many goroutines we need to put an untold solution in place.16:42
rogpeppeniemeyer: this would work, but you'll probably think it's messy: http://paste.ubuntu.com/1430008/16:42
niemeyerrogpeppe: How does conn.SetDeadline work?16:46
rogpeppeniemeyer: i think it hooks into net.TCPConn.SetDeadline, but i'll check16:46
niemeyerrogpeppe: It does.. but what happens when the deadline expires?16:47
rogpeppeniemeyer: you get an error that satisfies IsTimeout (IsTemporary?) AFAIR16:47
niemeyerrogpeppe: Sure, but the interesting question is what happens to the connection itself and the data that was being received when that takes place16:48
rogpeppeniemeyer: i *think* it may be left intact. but i don't think that helps us.16:49
rogpeppeniemeyer: if something is doing a ReadFull and it gets a temporary error, it is likely to be fatal16:50
niemeyerrogpeppe: Yeah, it'd likely introduce that kind of weird issue indeed16:51
rogpeppeniemeyer: something like this is fairly clean: http://paste.ubuntu.com/1430030/16:52
rogpeppeniemeyer: then the close can go in the function as you suggest16:53
niemeyerrogpeppe: Yeah, that looks like a nice directoin16:54
niemeyerrogpeppe: The error must be taken care of, etc, but looks nice16:54
rogpeppeniemeyer: that's what i was thinking of when i said16:55
rogpeppe[16:38:48] <rogpeppe> niemeyer: i mean we could read messages in a goroutine, and send them on a channel.16:55
rogpeppe[16:39:02] <rogpeppe> niemeyer: then select on that channel and Dying.16:55
rogpeppeniemeyer: i'm not sure what the best thing to do with the errors is though16:55
rogpeppeniemeyer: we don't want to take the whole server down because a single client sends an bogus request16:56
niemeyerrogpeppe: Indeed, I guess that's fine16:56
rogpeppeniemeyer: i think that a simple log message might be the best way16:56
niemeyerrogpeppe: +117:11
rogpeppeniemeyer: https://codereview.appspot.com/690207017:16
niemeyerrogpeppe: srv.run still returns an error that is never used.. its result is still used on Kill despite the fact it never changes17:18
rogpeppeniemeyer: ah, i'd forgotten that. will remove.17:18
niemeyerrogpeppe: Add and Done within websocket.Handler is still very awkward17:19
rogpeppeniemeyer: yes17:19
rogpeppeniemeyer: got a better solution?17:19
niemeyerrogpeppe: It is pretty much never sensible to call those in the same goroutine17:19
rogpeppeniemeyer: unfortunately we don't have control over the moment that http starts a new goroutine AFAIK17:20
rogpeppeniemeyer: i'm pretty sure my ErrStillAlive check makes the logic sound, but it is definitely awkward.17:21
niemeyerrogpeppe: Where is Wait?17:22
rogpeppeniemeyer: ha17:22
rogpeppeniemeyer: i'm sure it used to be *somewhere* :-)17:22
rogpeppeniemeyer: i was contemplating putting in a long-running request (some kind of waiter, perhaps) so that i could test these issues better17:25
niemeyerrogpeppe: Why do we need that goroutine at the start of run?17:25
rogpeppeniemeyer: it's either that or http.Serve17:26
rogpeppeniemeyer: hmm, and since we're not using the error returned by http.Serve, maybe we should just do "go http.Serve(...)"17:27
rogpeppeniemeyer: oh, but we can't17:27
rogpeppeniemeyer: it would look just the same as the other go statement17:27
niemeyerrogpeppe: Why?17:27
niemeyerrogpeppe: Why?17:27
rogpeppeniemeyer: we want to block until it's completed, i think17:28
niemeyerrogpeppe: Indeed, sounds like a good idea17:31
niemeyerrogpeppe: This also sounds a bit bogus, btw:17:35
niemeyer  71 »       »       // If we've got to this stage and the tomb is still17:35
niemeyer  72 »       »       // alive, we know that any tomb.Kill must occur after we17:35
niemeyer  73 »       »       // have called wg.Add, so we avoid the possibility of a17:35
niemeyer  74 »       »       // handler goroutine running after Stop has returned.17:35
rogpeppeniemeyer: PTAL (waitgroup added)17:35
niemeyerrogpeppe: Stop won't return before Done is called17:35
niemeyerrogpeppe: and we should not call Done while there's stuff running in background.. that's the invariant on tomb17:35
rogpeppeniemeyer: that's fine17:35
niemeyerrogpeppe:17:36
niemeyer  47 »       go func() {17:36
niemeyer  48 »       »       defer srv.tomb.Done()17:36
niemeyer  49 »       »       srv.run(lis)17:36
niemeyer  50 »       }()17:36
niemeyerrogpeppe: How about go srv.run(lis)?17:36
niemeyerrogpeppe: The Done there isn't right17:37
rogpeppeniemeyer: the Tomb.Done in the above code?17:37
niemeyerrogpeppe: Sorry, I guess it is now that you've added wg.Wait17:37
rogpeppeniemeyer: i *think* it's ok17:37
niemeyerrogpeppe: Still, we don't need a closure just to call a function17:37
rogpeppeniemeyer: good point.17:38
rogpeppeniemeyer: it was nice when it was returning an error, but now a bit redundant17:38
rogpeppeniemeyer: will make smaller17:38
niemeyerrogpeppe: Agreed on both points17:38
niemeyerrogpeppe: Line 152 will wedge on Dying17:41
rogpeppeniemeyer: argh, yes. it probably needs to select on dying too17:42
rogpeppeniemeyer: alternatively, we could close the conn and wait for readRequests to die, which might be cleaner.17:44
rogpeppeniemeyer: at least then we know we've cleaned up *all* resources17:44
niemeyerrogpeppe: closing under a sender?17:46
rogpeppeniemeyer: no17:46
rogpeppeniemeyer: http://paste.ubuntu.com/1430107/17:46
niemeyerrogpeppe: Doesn't look cleaner17:49
niemeyerrogpeppe: That means we'll have to Close twice, and wait for messages we don't care about just to unblock the other side17:49
rogpeppeniemeyer: it's cleaner in that no log messages can be produced after the server has been stopped17:50
rogpeppeniemeyer: i don't think we'll have to close twice17:50
niemeyerrogpeppe: So that paste already has a bug17:50
niemeyerrogpeppe: There are two returns.. one of them doesn't close the connection17:50
rogpeppeniemeyer: that's right17:50
niemeyerrogpeppe: !?17:50
rogpeppeniemeyer: does that invalidate the general approach?17:51
niemeyerrogpeppe: Sorry, I'm a bit lost.. it's right to not close the connection?17:52
rogpeppeniemeyer: no. but the piece i was trying to demonstrate was the bit that closes the connection and waits for the readRequests goroutine to finish17:53
niemeyerrogpeppe: All of the comments above were made about this17:53
rogpeppeniemeyer: i think this is different, as the readRequests goroutine has no side effects17:54
rogpeppeniemeyer: (this is a slightly different phrasing of the idea: http://paste.ubuntu.com/1430129/)17:54
niemeyerrogpeppe: I have no idea about what side effects has to do with the above points17:55
niemeyerrogpeppe: Either the paste had a missing Close, or it was Closing twice17:55
rogpeppeniemeyer: oh, sorry, i thought you were referring to much earlier comments17:55
rogpeppeniemeyer: "above" is, erm, ambiguous, in IRC context :-)17:55
niemeyerrogpeppe: You said it doesnt17:55
rogpeppeniemeyer: i said it doesn't what?17:56
niemeyerrogpeppe: So I don't know what you have in mind.. either way, all of that makes it sound like a bad idea.17:56
niemeyer<rogpeppe> niemeyer: i don't think we'll have to close twice17:56
rogpeppeniemeyer: did you look at my most recent paste?17:56
niemeyerrogpeppe: No, I'm still trying to understand what we're talking about17:56
niemeyerrogpeppe: We're clearly talking across each other17:56
niemeyerrogpeppe: And looking at more pastes won't help17:56
rogpeppeniemeyer: you were concerned about readRequests blocking forever when run returns, right?17:57
niemeyerrogpeppe: I made a very specific statement, saying that there was a missing Close or that it was closing twice17:57
niemeyerrogpeppe: You said "I don't think so", and didn't explain why, and ignored further comments17:58
rogpeppeniemeyer: my paste was supposed to be an explanation, sorry17:59
rogpeppeniemeyer: and the most recent paste shows how we can close once only, and reliably.17:59
niemeyerrogpeppe: Your different paste has different logic, and ignores my questioning18:00
niemeyerrogpeppe: "Yes, I wanted it to close twice"; "Yes, there was a bug".. those are all trivial to say18:00
niemeyerrogpeppe: and keep us on the same page18:00
rogpeppeniemeyer: your only question has been "it's right not to close the connection?"18:00
rogpeppeniemeyer: which sounds rhetorical to me - of course it's not right not to close the connection18:01
niemeyerrogpeppe: Sorry, that's not working at all18:01
niemeyerrogpeppe: I make a comment, and you say I'm wrong, and ignore it, and then say it's obvious that I'm right18:02
niemeyerrogpeppe: Just send the code you think is right for review then18:02
rogpeppeniemeyer: will do18:02
rogpeppeniemeyer: PTAL https://codereview.appspot.com/690207018:07
niemeyerrogpeppe: Done18:15
rogpeppeniemeyer: you're probably right that it's not worth saving one allocation per message :-)18:16
rogpeppeniemeyer: i wondered if you'd jump on that18:16
niemeyerrogpeppe: There's no allocation being saved in either case18:17
niemeyerrogpeppe: Both send the address of a local variable across to another function, and both send a copy of it over the channel. There's no reason for one to allocate and the other not.18:18
rogpeppeniemeyer: i think that the pointer passed to json.Unmarshal counts as escaping, so the local variable will be allocated each time round the loop18:18
niemeyerrogpeppe: See above18:18
rogpeppeniemeyer: it makes a difference if the variable is declared inside or outside the loop18:19
rogpeppeniemeyer: if it's declared outside, it will be allocated only once for the lifetime of the function18:20
rogpeppeniemeyer: if it's declared inside, it will be allocated each time it comes into scope (because it escapes)18:20
rogpeppeniemeyer: but still, it's only one allocation out of many, who cares? :-)18:20
niemeyerrogpeppe: Doesn't sound correct.. "escaping" is not defined by looping18:21
niemeyerrogpeppe: If you call f(&foo), the question is whether f keeps &foo or not18:21
rogpeppeniemeyer: no, "escaping" is defined by being passed to json.Unmarshal, in this case18:21
niemeyerrogpeppe: But really, it doesn't matter18:21
niemeyerrogpeppe: Yep, which both do18:21
niemeyerrogpeppe: I don't care, though.. this branch has been reviewed enough, and that's an early optimization anyway18:22
rogpeppeniemeyer: true18:22
rogpeppeniemeyer: i'll go with that18:22
rogpeppeniemeyer: for illustration: http://play.golang.org/p/9vsPOfjOmJ18:28
niemeyerrogpeppe: That's totally unrelated to escape analysis.. both are escaping.18:31
rogpeppeniemeyer: it illustrates the difference between the old version of the code and the new version of the code18:31
rogpeppeniemeyer: with "escape" standing in for some function that lets its argument escape18:31
rogpeppeniemeyer: (in our case JSON.Receive)18:32
niemeyerrogpeppe: Sure, I misunderstood what you meant.. it's obvious that it'll do more allocation *IF IT ESCAPES*18:32
niemeyerrogpeppe: <niemeyer> rogpeppe: If you call f(&foo), the question is whether f keeps &foo or not18:33
rogpeppeniemeyer: sure. and i'm absolutely certain that the argument the JSON.Unmarshal will escape. so we will allocate more.18:33
rogpeppeniemeyer: well, to be more accurate:18:33
rogpeppeniemeyer: the compiler can't tell that the argument doesn't escape18:34
niemeyerrogpeppe: There's zero intrinsic reason for it to escape18:34
niemeyerrogpeppe: Since it's side-effects free18:34
niemeyerrogpeppe: But.. I don't mind either way. Glad we've cleared the issue, though, thanks.18:34
rogpeppeniemeyer: yes, but it goes into reflect-based code, so the compiler throws up its hands and says "i dunno"18:34
niemeyerrogpeppe: Quite possibly18:35
rogpeppeniemeyer: just checked: http://play.golang.org/p/Wz7Z94cKaV18:36
niemeyerrogpeppe: Nice, feel free to revert the code if you want.18:38
rogpeppeniemeyer: submitted, thanks for the very useful review18:44
niemeyerrogpeppe: My pleasure18:44
rogpeppeniemeyer: time for me to go.18:44
rogpeppeniemeyer: and i guess we won't be seeing you for a little while18:45
rogpeppeniemeyer: good luck with everything!18:45
rogpeppeniemeyer: (i'm off tomorrow BTW)18:45
niemeyerrogpeppe: Ahh, cool, enjoy the holiday, and see you soon18:45
niemeyerrogpeppe: I'll certainly be around every now and then18:45
rogpeppeg'night all18:55
=== sidnei` is now known as sidnei

Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!