[squeak-dev] I'd like to contribute to the JSON project

Tobias Pape Das.Linux at gmx.de
Sun Nov 22 19:08:02 UTC 2020



> On 22. Nov 2020, at 19:37, Levente Uzonyi <leves at caesar.elte.hu> wrote:
> 
> Hi Tobias,
> 
> On Sun, 22 Nov 2020, Tobias Pape wrote:
> 
>> 
>> 
>>> On 22. Nov 2020, at 18:51, Levente Uzonyi <leves at caesar.elte.hu> wrote:
>>> Hi Tobias,
>>> On Sun, 22 Nov 2020, Tobias Pape wrote:
>>>>> On 22. Nov 2020, at 17:46, Levente Uzonyi <leves at caesar.elte.hu> wrote:
>>>>> Hi All,
>>>>> Since most (every?) practical use of #respondsTo: is to check whether it's safe to send the message or not, I think, contrary to what was mentioned in this thread, that #respondsTo: does not have to return true when sending the message would not result in an MNU.
>>>>> So, I suggest adding the following implementation to expose the dynamic nature of JsonObject:
>>>>> JsonObject >> #respondsTo: aSymbol
>>>>> 
>>>>> 	| precedence |
>>>>> 	(super respondsTo: aSymbol) ifTrue: [ ^true ].
>>>>> 	(precedence := aSymbol precedence) = 1 ifTrue: [
>>>>> 		^self includesKey: aSymbol ].
>>>>> 	(precedence = 3 and: [ (aSymbol indexOf: $:) = aSymbol size ]) ifTrue: [
>>>>> 		^self includesKey: aSymbol allButLast ].
>>>>> 	^false
>>>> That's nice! but why not make it simpler?
>>>> JsonObject >> #respondsTo: aSymbol
>>>> 
>>>> 	| precedence |
>>>> 	(super respondsTo: aSymbol) ifTrue: [ ^true ].
>>>> 	aSymbol isSimpleGetter ifTrue: [^self includesKey: aSymbol].
>>>> 	aSymbol isSimpleSetter ifTrue: [^self includesKey: aSymbol asSimpleGetter].
>>>> 	^false
>>> Three reasons:
>>> 1. performance
>>> | j s |
>>> Smalltalk garbageCollect.
>>> j := JsonObject new
>>> 	foo: 1;
>>> 	bar: 2;
>>> 	baz: 3;
>>> 	yourself.
>>> s := Symbol allSymbols.
>>> {
>>> 	[ s do: [ :each | ] ] bench.
>>> 	[ s do: [ :each | j respondsTo: each ] ] bench.
>>> 	[ s do: [ :each | j respondsTo2: each ] ] bench. "Your suggested implementation"
>>> }
>>> #(
>>> 	'1,630 per second. 613 microseconds per run. 0 % GC time.'
>>> 	'19 per second. 52.7 milliseconds per run. 0.09992 % GC time.'
>>> 	'1.18 per second. 850 milliseconds per run. 32.81709 % GC time.'
>>> )
>>> Okay, that may not be too a realistic workload. The reason of the extreme
>>> slowdown and high GC time is rapid interning and GCing of Symbols
>>> created by #asSimpleGetter.
>>> If you change s to a handcrafted array that avoids Symbol creation, like
>>> s := #(yourself foo foo: bar bar: baz baz: foobar foobar: name name:)
>>> the numbers get better but still not as good as my suggestion:
>>> #(
>>> 	'4,970,000 per second. 201 nanoseconds per run. 38.02 % GC time.'
>>> 	'147,000 per second. 6.82 microseconds per run. 1.74 % GC time.'
>>> 	'92,300 per second. 10.8 microseconds per run. 1.09978 % GC time.')
>> 
>> I thought you'd say that.
>> But "precedence" is one of the most obscure things around that part in the image.
>> 
>> 
>>> 2. backwards compatibility
>>> #isSimpleSetter and #isSimpleGetter are available since Squeak 5.3. I use this code in 5.1 and 5.2 images as well.
>> 
>> Yea, Pre 5.3 I'd have said #asMutator.
>> 
>>> 3. to use the same mechanism as #doesNotUnderstand:
>>> Have a look at that method.
>> 
>> 
>> Then I'd rather say change DNU too.
>> If you're down that hole (dnu/respondsTo) anyways, I don't buy the performance argument anymore.
>> 
>> Not everything has to be as fast as possible.
> 
> You seem to ignore that #doesNotUnderstand: is the most often used method of JsonObject.
> I assume you don't use the JSON package in production images, hence you don't care about performance.

I do.
It never has been the bottleneck.

> I do, so I'm not willing to change the implementation of #doesNotUnderstand: in my fork of the JSON package unless performance is at least as good as it is now.

I just want the image to remain tractable.
Performance is nice. But if you rely on performance with the JSOn stuff,
subclass the JsonObject and implement your keys as messages? That ought to be the fastest way, no?
I though it was meant to be that way.

That said, I rarely remain in the JSON space for longer than necessary; I'd rather have proper objects and only convert on "the edges"

I'm not against fast things.
I'm merely a bit startled by fast things that are harder to understand than necessary…

Best regards
	-Tobias

PS: Levente, your code is almost always the fastest variant of anything we discuss on here. That's amazing in itself. Don't get the impression I'm not amazed by that ;)

> 
> 
> Levente
> 
>> 
>> Best regards
>> 	-Tobias
>> 
>>> Levente
>>>> -Tobias
>>>>> Levente
>>>>> On Sun, 22 Nov 2020, Thiede, Christoph wrote:




More information about the Squeak-dev mailing list