Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using shallowCopy instead of appending to JsonObjects ? #1849

Closed
proddy opened this issue Jan 6, 2023 · 2 comments
Closed

using shallowCopy instead of appending to JsonObjects ? #1849

proddy opened this issue Jan 6, 2023 · 2 comments
Labels
question v6 ArduinoJson 6

Comments

@proddy
Copy link

proddy commented Jan 6, 2023

Hi,

With the release of 6.20.0 (can't wait for 6.21!) I was seeing if I can use the new shallowCopy() and optimize the memory usage and fragmentation on my ESP32 project.

My current pseudo code goes a bit like this:

	DynamicJsonDocument doc(4096);
   
	JsonObject json = doc.to<JsonObject>();
	
	// loop through devices build up the JSON payload
	for (const auto & device : alldevices) {
	
		JsonObject json_object = json;
		json_object  = doc.createNestedObject(device->unique_string());
		device->append_function(json_object)
	 
	} 
	
        // device class
	void Device::append_function(JsonObject& json_object) {
	
	      JsonObject json = json_object;
		  
	      for (another big loop) {
		   json[key] = data; // add lots of data
	      }
	
	}

So I'm dynamically going through class objects and building up a large JsonObject which could be close to 4kb, all in Heap, and then sending either over MQTT or HTTP GET response.

The questions I have is

  • Is it still best practice to create the JsonObject from the doc (using is using doc.to<JsonObject>()) and using this in a loop to append to it?
  • Could any of this be simplified or optimized using the new shallowCopy() ?

thanks

@proddy proddy added the question label Jan 6, 2023
@bblanchon
Copy link
Owner

Hi @proddy,

You could use the shallowCopy() function, but I don't think it'll simplify or optimize anything.

I'm assuming that your goal is to return a JsonDocument from the device like this:

class Device {
  virtual DynamicJsonDocument toJson() const = 0;
}

The problem is that shallowCopy() requires the source JsonDocument to remain in RAM.
We could do that with a vector like so:

DynamicJsonDocument doc(256); // <- can be much smaller
std::vector<DynamicJsonDocument> deviceDocs;   
	
for (const Device& device : alldevices) {
   deviceDocs.push_bash(device.toJson());
   doc[device->unique_string()].shallowCopy(deviceDocs.back());
} 

This should work but would degrade performance because this solution requires many more heap allocations.
The only benefit is that it lets the derived Device class decide on the capacity of its DynamicJsonDocument, allowing the memory consumption to be more dynamic.

I wouldn't use this solution because I prefer fixed memory allocation for its reliability.

Best regards,
Benoit

@proddy
Copy link
Author

proddy commented Jan 8, 2023

got it, thanks for the extensive explanation.

@proddy proddy closed this as completed Jan 8, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 8, 2023
@bblanchon bblanchon added the v6 ArduinoJson 6 label Feb 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question v6 ArduinoJson 6
Projects
None yet
Development

No branches or pull requests

2 participants