preface

To be a good Android developer, you need a completeThe knowledge systemHere, let’s grow up to be what we want to be.

Mind map of this article

I. Dimension of network optimization

1. Network optimization analysis

The efficiency of the basic network is like a train, the delay is the train’s speed (start time), while the bandwidth is like the train’s carriage load, and the entire physical link of transmission is like the train’s rails. From the perspective of network communication process, there are three modules involved:

  • 1) Internal design and strategy of network library SDK: I/O concurrency model, optimization for network problems.
  • 2) Server performance: concurrency and bandwidth capability.
  • 3) Network related: user network (weak network/strong network), carriers, network links, etc.

For network optimization, we can carry out from the following five dimensions.

1) Traffic optimization

Accurately obtain the consumption of network traffic, solve the problem of the whole mean covering up the single point of abnormal traffic.

2) Network monitoring

Build comprehensive network monitoring, because coarser grained monitoring cannot help us find and solve problems.

3) Flow consumption

  • 1. Accurately obtain the traffic consumption, network type, front and back of a period of time.
  • 2. Average consumption and abnormal rate of user traffic (more consumption and more times).
  • 3. Complete link monitoring (Request and Response) and active reporting.

4) Network request quality

  • 1. Request duration, service success rate, failure rate, TOP failed interface. There are two reasons for request failure:
    • 1), weak signal: can be simply seen as a mobile phone signal only one or two bars, this is not only signaling (wireless network communication is a signaling) to send difficult, but also may lead to continuous switching of the network, base station. Apps can only do retries at the application layer because weak signals are usually transient.
    • 2) Congested network: It can be likened to the scene of traffic jams and queues. Packets are queued and signaling is queued. At this point, the App keeps retrying, which will only make the network congestion more serious. We can only let their non-core business not to queue, and let the core business data volume is less, less protocol back and forth.
  • 2. User experience
  • 3, request speed, success rate: when the network is normal, how to better use the bandwidth to improve the network request speed?
  • 4. Weak network: How to maximize network connectivity due to network instability?
  • 5. Security: How to prevent being hijacked, eavesdropped or even tampered with by a third party?

5) Others

  • 1. Company costs
  • 2. Bandwidth, number of servers and CDN
  • 3, power consumption,

2, network optimization errors

  • 1) Only focus on traffic consumption and ignore other dimensions.
  • 2) Only focus on the mean, the whole, and ignore the individuals.

2. Network optimization tools

1, the Network Profiler

The characteristics of

  • 1) Display real-time network activity: sending and receiving data and connection number.
  • 2) Need to start advanced analysis.
  • 3) only HttpURLConnection and OkHttp are supported

Turn on advanced Analysis

Run => Edit Cofigurations => Enable advanced Profiling (Required for API level < 26 only)

Debug WanAndroid Network requests using Network Profiler

Select the target network request, and you can see the corresponding network data in the Connection View column below, as follows:

  • Size
  • Type
  • Status
  • Time
  • Timeline

Select a specific piece of data in the Connection View to see the network data corresponding to the request on the right.

Overview

Preview information for the network request

Normal Json data request

Image load request

Response

Response Header and Body information

Request

Request Header and Body information

CallStack

Call stack information for network requests. Here is the call stack for Awesome-WanAndroid to make a network request:

The call stack that Android goes through to make an image load request using Glide:

Key details

Required for API level < 26 in advanced configuration only if the phone version is less than 26, I can debug the phone using API 27.

New knowledge and insights gained through practice

If you want to quickly understand the w NETWORK request flow for the NETWORK/image loading framework in your project, you can use the Profiler NETWORK’s CallStack function and jump to specify the source code by double-clicking on any line to call the chain method.

Selected network request cannot display data?

Open advanced analysis.

2, Charles

Java development, MAC use more.

The characteristics of

  • 1) Breakpoint function
  • 2), Map Local
  • 3) Weak network environment simulation

Install the configuration

1, downloadCharles.

2. Intercepts network packets on mobile phones.

You need to configure your phone and computer to connect to the same WIFI.

1) Set Charles on the computer – Open the HTTP proxy and set the proxy port
  • Charles Menu bar => Proxy => Proxy Settings => Set Proxy port 8888 and Enable transparent HTTP proxying.
2) Set WIFI proxy and port on mobile terminal
  • Get the COMPUTER IP address
    • Click Charles’ help => local address.
  • Set the WIFI proxy and port number
    • Mobile phone Settings => WLAN => View the details of the current WIFI connection => Set the agent at the bottom to manual => Configure the COMPUTER IP address and port 8888.
3) After the setting is complete, run any networking program and Charles will pop up a confirmation box requesting connection. Click Allow.

3. Intercept HTTPS

Charles’ CA certificate needs to be trusted.

1) Open SSL proxy and configure Host and Port
  • Computer Proxy => SSL Proxying Setting => Select Enable SSL Proxying and click Add to set the Host and Port halves to * and 443.
2) Trust Charles Proxy CA
  • On the PC Help => SSL Proxying => Install Charles Proxy Root Certificate => Select and double-click Charles Proxy CA Root certification authority => Click Trust => Select Always Trust when using this Certificate.
3) Install the SSL certificate issued by Charles on the mobile terminal
  • On the PC Help => SSL Proxying => Install Charles Root Certificate on a Mobile Device. In this case, an information dialog box is displayed asking the Mobile phone to access chls.pro/ SSL to download the Certificate.
4) Install the certificate on the mobile terminal
  • Find the downloaded file from the file manager => If the file ends in. Pem I, change the file name extension to. CRT and click the file. => Enter the screen-lock password => Wait for the certificate to be imported and configure the certificate name (Charles).

Practice process

Select the target network request

From the Overview, you can see the comprehensive packet information.

Using breakpoints

1) Right-click the URL you want to break and select BreakPoints to enable BreakPoints.
2) Click the top Proxy => Breadkpoint Settings.
3) double-click the target in the Breakpoints Settings panel

URL, in the Edit Breakpoint panel that pops up.

4) Here, breakpoint Request and Response are selected by default. We can select only breakpoint Response or Request. Click OK to complete the breakpoint setting.
5) Then, click Edit Response on the right side of the main panel to Edit Response, and click Execute at the bottom after the modification is complete.

Using the Map Local

1) Freely simulate the data returned by the server to test the interface in advance.
1) Right-click the URL to use Map Local and select Map Local to enable the breakpoint function.
1) Then, in the Edit Mapping panel, select the Local path of Map To and the Local maplocal data set locally (for example, JsonString).

Weak network simulation

  • 1. Before enabling Map Local, disable Map Local.

  • 2) Click Proxy => Throttle Setting => Select Enable Throttling

  • 3) There are many preset simulation Settings, we only need to set the Throttle preset rate of network packet transmission to a low rate (generally set to 256/512).

Problems encountered

  • 1) Note that the mobile phone and the laptop need to be under the same WIFI, so it is not allowed to open a hotspot or use the Intranet of the company. Otherwise, the confirmation box indicating that the mobile phone is connected to Charles cannot pop up on the computer, and the SSL certificate provided by Charles cannot be downloaded.
  • 2) It is better not to use the system browser when downloading the SSL certificate provided by Charles on the mobile terminal.

3, Wireshark

Geektime-webprotocol is highly recommended

The WireShark can be used to trace the following four streams:

  • TCP
  • UDP
  • SSL
  • HTTP

1) Basic use of WireShark

How to Capture a Message

  • 1) Click Capture -> Options to open the capture window
    • Network adapter device/traffic/capture filter, click Start to start packet capture
    • Output (specify cache file)/ options (display, name resolution, automatic stop packet capture condition) panel
  • 2) Click Capture -> Stop to stop packet capture

Wireshark panel

Shortcut toolbar

Packet color (View -> Coloring Rules)

Set the time display format

The symbol for the packet list panel

File operations

  • 1) Mark the message Ctrl+M.
  • 2) export marked packets (file -> export specific group), or export packets according to the filter,
  • 3) Read multiple packets (file -> merge).

How do I quickly capture packets from mobile devices?

  • 1. Turn on your phone’s wifi hotspot.
  • 2. Connect your computer to your phone’s wifi hotspot.
  • 3. Use the Wireshark to open the Capture > Options panel and select the interface device corresponding to the wifi hotspot to capture packets.

2) The Wireshark filter

If the expression’s background is green, the filter’s syntax is correct, and red indicates an error.

Capture filter

It is used to reduce the volume of captured packets. It uses Berkeley Packet Filter (BPF) syntax and has relatively limited functions.

BPF provides a packet capture filtering interface at the device driver level. Most packet capture tools support this syntax. The Expression of BPF consists of primitives. Each primitives primitive consists of a name or number and multiple Qualifiers that describe it.

The qualifiers qualifier
  • 1. Type: Sets the Type indicated by the number or name
    • The host and the port.
    • Net: set the subnet. Net 192.168.0.0 mask 255.255.255.0 Is equivalent to NET 192.168.0.0/24.
    • Portrange, set the portrange, for example portrange 6000-8000.
  • 2. Dir: Sets the network inbound and outbound direction
    • SRC, DST, SRC or DST, SRC and DST.
    • Ra, TA, ADDR1, ADDR2, ADDR3, adDR4 (valid for IEEE 802.11 Wireless LAN only).
  • 3. Proto: Specifies the protocol type
    • Ether, FDDI, tr, WLAN,
    • IP, IP6, ARP, RARP,
    • Decnet, TCP, UDP, ICMP, IGMP, ICMP
    • Igrp, PIM, AH, ESP, and VRRP
  • 4, other
    • Gateway: Indicates the gateway IP address. It is equivalent to ether host ehost and not host host.
    • Broadcast: indicates broadcast packets, such as ether broadcast or IP broadcast.
    • Multicast: Multicast packets, such as IP multicast or IP6 multicast.
    • Less, greater: the value is less than or greater than the value.

A simple example

src or dst portrange 6000-8000 && tcp or ip6
Copy the code

Display filter

It filters and displays the captured packets.

Filtering based on protocol domain
  • Capture all RST packets in TCP: TCP [13]&4==4.
  • Capture HTTP GET packets: port 80 and TCP [((TCP [12:1] &0xf0) >> 2):4] = 0x47455420. (47455420 is ASCII hexadecimal, meaning “GET”)
  • Capture HTTP POST packets: port 80 and TCP [((TCP [12:1] &0xf0) >> 2):4] = 0x504F5354
Displays the filter properties of the filter

Any field name resolved in the packet detail panel can be used as the filtering attribute. In view -> Inside -> Supported Protocols, you can see the attribute names corresponding to each field name. For example, the Source Port in the TCP header in the packet details panel corresponds to the filtering attribute tcp.srcPort.

Common operators
  • 1), and (&&) : and logic and, ip.src==10.0.0.5 and tcp.flags.fin.
  • 2), or (| |) : the or logic or IP. The SCR = = 10.0.0.5 or IP. The SRC = = 192.1.1.1.
  • 3), xOR (^^) : xOR logic Xor, tr.dst[0:3] == 0.6.29 xor tr.src[0:3] == 0.6.29.
  • 4), not (!) : NOT Logical NOT, NOT LLC.
  • 5), […]. : brackets []Slice Slice operator
    • [n:m] Indicates that n is the start offset and m is the slice length, for example, eth. SRC [0:3] == 00:00:83
    • [n-m] Indicates that n is the start offset, and m is the end offset. For example, eth. SRC [1-2] == 00:83
    • [:m] indicates the offset from the start to the end of M, for example, eth. SRC [:4] == 00:00:83:00
    • [m:] indicates that M is the start offset to the end of the field, for example, eth. SRC [4:] == 20:20
    • [m] Indicates the byte at the offset m, for example, eth. SRC [2] == 83
    • [and] when separated by a comma, allow the above ways at the same time, for example: the eth. SRC [3-0, 1-2, : 4, 4:, 2) = = 00:00:8 3:00:8 3:00:00:83:00:20:20:83
  • 6), in: braces {} set operator, for example tcp.port in {443 4430.. . 4434}, equivalent to the actual TCP port 443 = = | | (TCP) port > = 4430 && TCP port ⇐ 4434).
Available functions
  • Upper: Converts a string field to uppercase.
  • Lower: Converts a string field to lowercase.
  • Len: Returns the length in bytes of a string or byte array.
  • Count: Returns the number of fields that appear in a frame.
  • String: Converts a non-string field to a string.
Displays a visual dialog for the filter

Ring buffer

For example, use a ring cache with three files, starting from **.1 => **.2 => **.3 and then starting from **.1 to form a ring.

TcpDump (network packet sniffer)

1. Procedure of packet capture

1. Obtain a mobile phone with ROOT permission

2, downloadtcpdump

Install tcpdump on your phone

adb push tcpdump /data/local/tmp
Copy the code

4. Modify the permission on the tcpdump to make it executable

chmod 777 /data/local/tmp/tcpdump
Copy the code

5. Run the tcpdump command to capture packets. Press Ctrl + C to stop packet capture

6. Save the captured packets as a Pcap file. In this case, you only need to add the -w parameter after running the tcpdump

tcpdump-w /data/local/tmp/tcp.pcap
Copy the code

7. Copy the Pcap to the computer and use Wireshark to analyze the data packet traffic.

2) Capture and stop conditions

  • -d: lists all network adapter devices.
  • -i: selects the nic device.
  • -c: indicates the number of packets to be captured.
  • –time-stamp-precision: specifies the time precision of capture. The default value is micro, nanosecond is optional.
  • -s: specifies the maximum number of bytes in each packet. The default value is 262144 bytes.

3) File operation

  • -w: Outputs the result to a file that can be read and analyzed by the Wireshark.
  • -c: limits the size of the input file. If the size exceeds the limit, the file size is incremented by a suffix such as 1. Note that the units are 1,000,000 bytes.
  • -w: specifies the maximum number of output files. The first file will be overwritten after the number reaches.
  • -g: specifies that the output is reprinted to the new file every N seconds. Note that the -w parameter should be based on

The strftime parameter specifies the file name.

  • -r: reads a captured packet file.
  • -v: writes multiple file names to be read into a file and reads multiple files at the same time.

4) Output timestamp format

  • -t: the time stamp is not displayed.
  • – TT: the number of seconds since 0:00 on January 1, 1970.
  • – TTT: displays the number of seconds between two neighboring packets.
  • – TTTT: Complete time with date.
  • – TTTTT: indicates the number of seconds since the first captured packet.

5) Analyze information details

  • -e: displays the data link layer header.
  • -q: The transport layer information is not displayed.
  • -v: displays more information about the network layer header, such as the TTL and ID.
  • -n: Displays the IP address and digital port instead of hostname.
  • -s: Indicates that the absolute sequence number is replaced by the relative sequence number.
  • -a: displays the packet content in ASCII mode and applies to HTTP analysis.
  • -x: displays the packet contents in hexadecimal mode. The data link layer is not displayed.
  • -xx: displays the packet contents in hexadecimal mode and the data link layer.
  • -x: Displays the packet contents in both hexadecimal and ACII modes. The data link layer is not displayed. • -xx Displays the packet contents in both hexadecimal and ACII modes, and the data link layer is displayed.

5, Stetho

  • 1), in the build. Gradle, besides Stetho dependence, still need to add ‘com. Facebook. Stetho: Stetho – okhttp3:1.5.0’.
  • 2), in the onCreate method Application initialization ‘Stetho. InitializeWithDefaults (this)’.
  • 3) Call the ‘addNeworkInterceptor’ method of OkHttp to add the network interceptor provided by Stetho for collecting network information.
  • 4), go to the Chrome debug page ‘Chrome ://inspect’.

6, other performance testing tools

  • Strace: Tracks system calls related to sockets.
  • Netstat: records the statistics of multiple network stacks and interfaces.
  • Ifconfig: records interface configurations.
  • IP: Records statistics about network interfaces.
  • Ping: tests network connectivity.
  • Traceroute: tests the network route.
  • The/proc /.net command: To view network statistics, Android TrafficState uses the /proc/net/xt_qtaguid/stats and /proc/net/xt_qtaguid/iface_stat_fmt files to collect App traffic statistics.

Three, accurate access to flow consumption

1. How to judge App traffic consumption is high?

  • 1), the absolute value can not be seen.
  • 2) Compare competing products, and compare vagrant consumption in the same Case.
  • 3) Abnormal monitoring exceeds normal indicators.

2. Test scheme

  • 1) Open the phone Settings => Traffic Management => Only allow the target App to connect to the Internet
  • 2) Can find out most of the problems, but the online scene offline may not meet.

3. Online traffic acquisition scheme

1), TrafficStats

The characteristics of

  • API 18 or above.
  • Record the data traffic since the phone was restarted.

API

  • GetMobileRxBytes () : Information received through cellular traffic.
  • GetUidRxBytes (int UID) : Obtains the received traffic with a specified UID.
  • GetTotalRxBytes () : indicates the total sent traffic.

disadvantages

The traffic consumption in a certain period cannot be obtained.

2), NetworkStatsManager

After API 23.

The characteristics of

  • 1) Obtain the traffic information within the specified interval.
  • 2) Obtain the consumption under different network types.

NetUtils.getStats

Gets total cellular + WIFI traffic information at a specified interval

4. Front and background traffic acquisition scheme

Question: Does online feedback App consume much traffic the day after tomorrow?

Obtaining only one period of traffic is not comprehensive.

Realize the principle of

Background scheduled task => Obtain the traffic within the interval => Record the traffic in the background => calculate the traffic separately => report the traffic to the APM background => Traffic management basis

summary

  • 1) The scheme cannot obtain the traffic of the application in the front and background switchover, so there is a certain error, but this error is acceptable.
  • 2) Combined with refined abnormal flow alarm, targeted to solve the problem of background running flow.

The success log is as follows:

2020-05-11 10:47:55.633 4036-4181/ json.chao.com.wanandroid I/WanAndroid - LOG: │ [MainActivity. Java |193 | lambda$initEventAndData$1$MainActivity] backNetUseData: 4 MB
2020-05-11 10:47:55.646 4036-4181/ json.chao.com.wanandroid I/WanAndroid - LOG: │ [MainActivity. Java |194 | lambda$initEventAndData$1$MainActivity] foreNetUseData: 4 MB
2020-05-11 10:47:55.652 4036-4181/ json.chao.com.wanandroid I/WanAndroid - LOG: │ [MainActivity. Java |197 | lambda$initEventAndData$1$MainActivity] totalNetUseData: 8 MB
Copy the code

Fourth, network request traffic optimization

1. Common Network scenarios

1) Data compression

The Body of the POST request is GZip compressed, and the Body returned by the server is GZip compressed.

2) Pictures

  • Compress images before uploading.
  • Image use strategy refinement: let the server /CDN cloud server preferrly use thumbnail /WebP format images.

3) Performance log reporting: Report performance logs in batches and in specific scenarios

APM related, single point problem related. For example, buried data can be uploaded at a certain time point (such as when WIFI is enabled and part of the data must be uploaded due to a large amount of data).

4) Data cache

The server returns the expiration time to avoid re-obtaining each time. Save traffic and greatly improve data access speed, better user experience.

Request Cache Settings

  • Pragma:no-cache: pull the latest resources from the server without cache.
  • 2, if-modified-since :datetime: If the resource has changed after the time provided by the client, the server will return the new resource, otherwise use the cache.
  • 3. If-none-match :etagvalue: returns a new resource If the resource id is different from that of the server.

If the Request header is 2 or 3, the server will return HTTP/304 Not Modified, and the client will use the cached Response.

Response Cache Settings

Whether an HTTP Response can be cached is controlled by the Response header. The server can Control how the Response is cached on the client through Expires and cache-control.

Expires

The Expires header contains a date, which is the expiration date of the resource cache. When a client has a new request for the same resource, if the resource cache has not expired, the cached resource is used and the server does not return anything.

Cache-Control

Cache-control specifies how Response is stored and how it is used. Its options are as follows:

  • 1), public: Response can be stored in any Cache, including shared Cache.
  • 2), private: Response is stored in private Cache and can only be used by one user.
  • 3) no-cache: Response will not be used in the future
  • 4), no-store: Response will not be used in the future and will not be written to disk.
  • 5), max-age=#seconds: Response can be used repeatedly within the specified time.
  • 6), must-revalidate: After confirming that the Response from the original server is the latest, the cache can be used.

OKHttp netless data cache implementation

POST is not cached in OKHttp by default because it is usually used to modify data. The httpModule-CacheInterceptor in Awesome-WanAndroid already implements the unnetted data cache of OKHttp, as shown in this code:

File cacheFile = new File(Constants.PATH_CACHE);
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
Interceptor cacheInterceptor = chain -> {
    Request request = chain.request();
    if(! CommonUtils.isNetworkConnected()) {// Data caching is mandatory when no network is available to improve user experience.
        request = request.newBuilder()
                .cacheControl(CacheControl.FORCE_CACHE)
                .build();
    }
    Response response = chain.proceed(request);
    if (CommonUtils.isNetworkConnected()) {
        int maxAge = 0;
        // When there is a network, the cache is not used. The maximum storage duration is 0
        response.newBuilder()
                .header("Cache-Control"."public, max-age=" + maxAge)
                .removeHeader("Pragma")
                .build();
    } else {
        // If no network is available, set the timeout to 4 weeks
        int maxStale = 60 * 60 * 24 * 28;
        response.newBuilder()
                .header("Cache-Control"."public, only-if-cached, max-stale=" + maxStale)
                .removeHeader("Pragma")
                .build();
    }
    return response;
};
// Cache optimization
builder.addNetworkInterceptor(cacheInterceptor);
builder.addInterceptor(cacheInterceptor);
builder.cache(cache);
Copy the code

5) Offline package and incremental data update

With the concept of versioning, only variable data is transmitted.

6) Request header compression

If the headers are not changed, the server can use the mapping to cache the MD5: request header and then use MD5 for all subsequent requests.

7) Optimize the transmission frequency and timing

8) Merge network requests and reduce the number of requests.

9), flow bottom pocket ability

If we find abnormal traffic, we can terminate the protocol interaction through the backend server to avoid worsening the problem.

2. Traffic statistics

We can use network-connection-class traffic statistics, which internally uses API 8’s TrafficStats class to get the network traffic of the entire phone or a particular UID from startup.

1) Four core apis

// Total number of bytes received by the Mobile network from startup, excluding Wifi
getMobileRxBytes()        
// Total number of bytes received by all networks from startup, including Wifi
getTotalRxBytes()     
// Total number of bytes sent by the Mobile network from startup, excluding Wifi
getMobileTxBytes()        
// Total number of bytes sent by all networks from startup, including Wifi
getTotalTxBytes()         
Copy the code

2) The corresponding Linux kernel proc statistics interface

// The STATS interface provides traffic information for each UID on each network interface (WLAN0, PPP0, etc.)
/proc/net/xt_qtaguid/stats
// Iface_stat_fmt provides summary traffic information of each interface
proc/net/xt_qtaguid/iface_stat_fmt
Copy the code

3) Working principle

  • 1) read the proc and add the traffic of all network interfaces under the target UID.
  • 2) After Android 7.0, you can only get TrafficStats for your app.

Reference links:


  • 1, MOOCs Top team with you to play Android performance analysis and optimization chapter 8 App network optimization
  • 2, Geek time Android Development master course network optimization
  • 3, “Android mobile Performance combat” chapter 3 network
  • 5. Geek Time Web protocol detailed explanation and actual packet capture
  • 5, geektime – geekbang/geektime – webprotocol
  • 6. Wanandroid network optimization
  • 7, Chrome TLS1.3 Settings
  • 8. Mobile network optimization practices of Meituan-Dianping
  • 9, Mogujie App Chromium network stack practice
  • 10. Wechat Mars — Exploring high-quality Internet Connections under the Mobile Internet. PDF
  • 11. Mars — Cross-platform cross-business basic component of wechat
  • 12. Ali Wireless 11.11: Evolution of Access gateway infrastructure of Mobile Taobao Terminal
  • 13. Jia Dao: Analyzing the architecture of mobile end-to-end network access under 100-level concurrency of Ant Financial
  • 14. Network performance optimization practice of Ctrip App
  • 15. Baidu App Network Depth Optimization series “1” DNS optimization
  • 16, Google/brotli
  • 17, facebook/ZSTD
  • 18, See “deep”, see “clear” — the application of deep learning in image ultra clear
  • TLS1.3 VS TLS1.2, let you understand the power of TLS1.3
  • 20. Introduction of TLS1.3 based wechat security communication protocol MMTLS
  • 21. How did Facebook make TLS connections more efficient?
  • 22, SSL Pinning Practice
  • How can P2P reduce the bandwidth of live video by 75%?
  • 24, BBR: Congestion-based Congestion Control
  • 25. Application practice of QUIC in mobile microblog. PDF
  • 26. Hook Socket Sample
  • 27. RFC directory

Thank you for reading this article. I hope you can share it with your friends or tech groups. It means a lot to me.

I hope we can be friends beforeGithub,The Denver nuggetsLast time we shared our knowledge.